diff --git a/pom.xml b/pom.xml index d2516199..1ccae5b2 100644 --- a/pom.xml +++ b/pom.xml @@ -142,7 +142,7 @@ org.ohdsi.sql SqlRender - 1.6.8 + 1.16.1-SNAPSHOT test diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/CohortExpressionQueryBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/CohortExpressionQueryBuilder.java index bf65f8ab..4f167eb0 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/CohortExpressionQueryBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/CohortExpressionQueryBuilder.java @@ -20,9 +20,13 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; + +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.apache.commons.lang3.StringUtils; @@ -45,7 +49,6 @@ public class CohortExpressionQueryBuilder implements IGetCriteriaSqlDispatcher, 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 WINDOWED_CRITERIA_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/windowedCriteria.sql"); @@ -97,6 +100,9 @@ public static class BuildExpressionQueryOptions { @JsonProperty("cohortId") public Integer cohortId; + + @JsonProperty("resultCohortId") + public Integer resultCohortId; @JsonProperty("cdmSchema") public String cdmSchema; @@ -113,6 +119,9 @@ public static class BuildExpressionQueryOptions { @JsonProperty("generateStats") public boolean generateStats; + @JsonProperty("retainCohortCovariates") + public boolean retainCohortCovariates; + public static CohortExpressionQueryBuilder.BuildExpressionQueryOptions fromJson(String json) { try { CohortExpressionQueryBuilder.BuildExpressionQueryOptions options @@ -144,13 +153,35 @@ private String getAdditionalColumns(List columns, String prefix) return String.join(",", columns.stream().map((column) -> { return prefix + column.columnName();}).collect(Collectors.toList())); } - private String wrapCriteriaQuery(String query, CriteriaGroup group) { + private String wrapCriteriaQuery(String query, CriteriaGroup group, BuilderOptions options, Criteria criteria) { String eventQuery = StringUtils.replace(EVENT_TABLE_EXPRESSION_TEMPLATE, "@eventQuery", query); - String groupQuery = this.getCriteriaGroupQuery(group, String.format("(%s)", eventQuery)); + + // Add the fields concept_id, value_as_number, value_as_string, value_as_concept_id, unit_concept_id,... if the save covariates checkbox is checked + + ArrayList selectColsPE = new ArrayList<>(); + if (options.isRetainCohortCovariates()) { + eventQuery = StringUtils.replace(eventQuery, "@concept_id", ", Q.concept_id"); + eventQuery = criteria.embedWrapCriteriaQuery(eventQuery, selectColsPE, options); + } else { + eventQuery = StringUtils.replace(eventQuery, "@concept_id", ""); + eventQuery = StringUtils.replace(eventQuery, "@QAdditionalColumnsInclusionN", ""); + } + String groupQuery = this.getCriteriaGroupQuery(group, String.format("(%s)", eventQuery), options.isRetainCohortCovariates()); groupQuery = StringUtils.replace(groupQuery, "@indexId", "" + 0); String wrappedQuery = String.format( - "select PE.person_id, PE.event_id, PE.start_date, PE.end_date, PE.visit_occurrence_id, PE.sort_date FROM (\n%s\n) PE\nJOIN (\n%s) AC on AC.person_id = pe.person_id and AC.event_id = pe.event_id\n", + "select PE.person_id, PE.event_id" + + "@concept_id" + + "@PEAdditionalColumnsInclusionN" + + ", PE.start_date, PE.end_date, PE.visit_occurrence_id, PE.sort_date 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); + // Add the fields concept_id, value_as_number, value_as_string, value_as_concept_id, unit_concept_id if the save covariates checkbox is checked + if (options.isRetainCohortCovariates()) { + wrappedQuery = StringUtils.replace(wrappedQuery, "@concept_id", ", PE.concept_id"); + wrappedQuery = StringUtils.replace(wrappedQuery, "@PEAdditionalColumnsInclusionN", StringUtils.join(selectColsPE, "")); + } else { + wrappedQuery = StringUtils.replace(wrappedQuery, "@concept_id", ""); + wrappedQuery = StringUtils.replace(wrappedQuery, "@PEAdditionalColumnsInclusionN", ""); + } return wrappedQuery; } @@ -177,24 +208,26 @@ public String getCodesetQuery(ConceptSet[] conceptSets) { } - private String getCensoringEventsQuery(Criteria[] censoringCriteria) { + private String getCensoringEventsQuery(Criteria[] censoringCriteria, BuilderOptions builderOptions) { ArrayList criteriaQueries = new ArrayList<>(); for (Criteria c : censoringCriteria) { - String criteriaQuery = c.accept(this); + String criteriaQuery = c.accept(this, builderOptions); criteriaQueries.add(StringUtils.replace(CENSORING_QUERY_TEMPLATE, "@criteriaQuery", criteriaQuery)); } return StringUtils.join(criteriaQueries, "\nUNION ALL\n"); } - public String getPrimaryEventsQuery(PrimaryCriteria primaryCriteria) { + public String getPrimaryEventsQuery(PrimaryCriteria primaryCriteria, BuilderOptions builderOptions) { String query = PRIMARY_EVENTS_TEMPLATE; ArrayList criteriaQueries = new ArrayList<>(); - + + builderOptions.setPrimaryCriteria(true); for (Criteria c : primaryCriteria.criteriaList) { - criteriaQueries.add(c.accept(this)); + criteriaQueries.add(c.accept(this, builderOptions)); } + builderOptions.setPrimaryCriteria(false); query = StringUtils.replace(query, "@criteriaQueries", StringUtils.join(criteriaQueries, "\nUNION ALL\n")); @@ -262,19 +295,39 @@ public String buildExpressionQuery(String expression, BuildExpressionQueryOption return this.buildExpressionQuery(CohortExpression.fromJson(expression), options); } + // Function all full field select for union all + private void addColumnFieldInclusionGroup(List> listFields, CriteriaGroup cg, int indexCG, + List inclusionRuleInsertN, List inclusionRuleGroupN) { + + listFields.forEach(l -> { + if (listFields.indexOf(l) == indexCG) { + l.forEach(s -> { + inclusionRuleInsertN.add(", " + s.getName() + " " + s.getName() + "_" + indexCG); + inclusionRuleGroupN.add(", AC." + s.getName()); + }); + } else { + l.forEach(s -> inclusionRuleInsertN + .add(", CAST(null as " + s.getDataType().getType() + ") " + s.getName() + "_" + + listFields.indexOf(l))); + } + }); + } + 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); + BuilderOptions builderOptions = new BuilderOptions(); + builderOptions.setRetainCohortCovariates(options != null && options.retainCohortCovariates); + String primaryEventsQuery = getPrimaryEventsQuery(expression.primaryCriteria, builderOptions); resultSql = StringUtils.replace(resultSql, "@primaryEventsQuery", primaryEventsQuery); String additionalCriteriaQuery = ""; if (expression.additionalCriteria != null && !expression.additionalCriteria.isEmpty()) { CriteriaGroup acGroup = expression.additionalCriteria; - String acGroupQuery = this.getCriteriaGroupQuery(acGroup, String.format("(%s)", primaryEventsQuery));//acGroup.accept(this); + String acGroupQuery = this.getCriteriaGroupQuery(acGroup, String.format("(%s)", primaryEventsQuery), options.retainCohortCovariates);// 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"; } @@ -289,23 +342,70 @@ public String buildExpressionQuery(CohortExpression expression, BuildExpressionQ resultSql = StringUtils.replace(resultSql, "@QualifiedLimitFilter", ""); } + List> listField = new ArrayList<>(); if (expression.inclusionRules.size() > 0) { ArrayList inclusionRuleInserts = new ArrayList<>(); ArrayList inclusionRuleTempTables = new ArrayList<>(); - + + // Add column field for inclusion group needed to listField for (int i = 0; i < expression.inclusionRules.size(); i++) { + CriteriaGroup cg = expression.inclusionRules.get(i).expression; + if (cg.criteriaList == null || cg.criteriaList.length == 0) { + listField.add(new ArrayList<>()); + } else { + Map mapDistinctField = new HashMap<>(); + for (CorelatedCriteria cc : cg.criteriaList) { + cc.criteria.getSelectedField(options.retainCohortCovariates).forEach(c -> { + mapDistinctField.put(c.getName(), c); + }); + } + listField.add(mapDistinctField.entrySet().stream().map(e -> e.getValue()).collect(Collectors.toList())); + } + } + + for (int i = 0; i < expression.inclusionRules.size(); i++) { + ArrayList lstFieldRuleInsertNValues = new ArrayList<>(); CriteriaGroup cg = expression.inclusionRules.get(i).expression; - String inclusionRuleInsert = getInclusionRuleQuery(cg); + String inclusionRuleInsert = getInclusionRuleQuery(cg, options != null && options.retainCohortCovariates); inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@inclusion_rule_id", "" + i); - inclusionRuleInserts.add(inclusionRuleInsert); inclusionRuleTempTables.add(String.format("#Inclusion_%d", i)); + + if (options != null && options.retainCohortCovariates) { + ArrayList inclusionRuleInsertN = new ArrayList<>(); + ArrayList inclusionRuleGroupN = new ArrayList<>(); + inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@conceptid", ", pe.concept_id"); + + this.addColumnFieldInclusionGroup(listField, cg, i, inclusionRuleInsertN, inclusionRuleGroupN); + + lstFieldRuleInsertNValues.add(StringUtils.join(inclusionRuleInsertN, "")); + + inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@additionalColumnsInclusionN", StringUtils.join(lstFieldRuleInsertNValues, " ")); + inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@additionalColumnsCriteriaQuery", StringUtils.join(inclusionRuleGroupN, " ")); + } else { + inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@concept_id", ""); + inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@additionalColumnsInclusionN", ""); + inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@conceptid", ""); + inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@additionalColumnsCriteriaQuery", ""); + } + inclusionRuleInserts.add(inclusionRuleInsert); + } + String irTempUnion = ""; + if (options != null && options.retainCohortCovariates) { + irTempUnion = inclusionRuleTempTables.stream() + .map(d -> String.format("select %s.* \n" + + "from %s \n", d, d)) + .collect(Collectors.joining("\nUNION ALL\n")); + inclusionRuleInserts.add(String.format("SELECT * INTO #inclusion_events\nFROM (%s) I;", irTempUnion)); + + } else { + irTempUnion = inclusionRuleTempTables.stream() + .map(d -> String.format("select inclusion_rule_id, person_id, event_id from %s", d)) + .collect(Collectors.joining("\nUNION ALL\n")); + inclusionRuleInserts.add(String.format("SELECT inclusion_rule_id, person_id, event_id\nINTO #inclusion_events\nFROM (%s) I;", irTempUnion)); - String irTempUnion = inclusionRuleTempTables.stream() - .map(d -> String.format("select inclusion_rule_id, person_id, event_id from %s", d)) - .collect(Collectors.joining("\nUNION ALL\n")); + } - inclusionRuleInserts.add(String.format("SELECT inclusion_rule_id, person_id, event_id\nINTO #inclusion_events\nFROM (%s) I;", irTempUnion)); inclusionRuleInserts.addAll(inclusionRuleTempTables.stream() .map(d -> String.format("TRUNCATE TABLE %s;\nDROP TABLE %s;\n", d, d)) @@ -334,17 +434,27 @@ public String buildExpressionQuery(CohortExpression expression, BuildExpressionQ if (expression.endStrategy != null) { // replace @strategy_ends placeholders with temp table creation and cleanup scripts. - resultSql = StringUtils.replace(resultSql, "@strategy_ends_temp_tables", expression.endStrategy.accept(this, "#included_events")); + resultSql = StringUtils.replace(resultSql, "@strategy_ends_temp_tables", expression.endStrategy.accept(this, "#included_events", options != null && options.retainCohortCovariates)); resultSql = StringUtils.replace(resultSql, "@strategy_ends_cleanup", "TRUNCATE TABLE #strategy_ends;\nDROP TABLE #strategy_ends;\n"); + resultSql = StringUtils.replace(resultSql, "@paramEraStrategy", ", era_end_date"); + resultSql = StringUtils.replace(resultSql, "@insertEraStrategy", ", se.end_date"); endDateSelects.add(String.format("-- End Date Strategy\n%s\n", "SELECT event_id, person_id, end_date from #strategy_ends")); + if (options != null && options.retainCohortCovariates) { + resultSql = StringUtils.replace(resultSql, "@strategy_ends_columns", ", se.end_date strategy_end_date"); + resultSql = StringUtils.replace(resultSql, "@leftjoinEraStrategy", "left join #strategy_ends se on qe.person_id = se.person_id AND qe.event_id = se.event_id"); + } } else { // replace @trategy_ends placeholders with empty string resultSql = StringUtils.replace(resultSql, "@strategy_ends_temp_tables", ""); resultSql = StringUtils.replace(resultSql, "@strategy_ends_cleanup", ""); + resultSql = StringUtils.replace(resultSql, "@paramEraStrategy", ""); + resultSql = StringUtils.replace(resultSql, "@insertEraStrategy", ""); } + resultSql = StringUtils.replace(resultSql, "@leftjoinEraStrategy", ""); + resultSql = StringUtils.replace(resultSql, "@strategy_ends_columns", ""); if (expression.censoringCriteria != null && expression.censoringCriteria.length > 0) { - endDateSelects.add(String.format("-- Censor Events\n%s\n", getCensoringEventsQuery(expression.censoringCriteria))); + endDateSelects.add(String.format("-- Censor Events\n%s\n", getCensoringEventsQuery(expression.censoringCriteria, builderOptions))); } resultSql = StringUtils.replace(resultSql, "@finalCohortQuery", getFinalCohortQuery(expression.censorWindow)); @@ -352,11 +462,9 @@ public String buildExpressionQuery(CohortExpression expression, BuildExpressionQ resultSql = StringUtils.replace(resultSql, "@cohort_end_unions", StringUtils.join(endDateSelects, "\nUNION ALL\n")); resultSql = StringUtils.replace(resultSql, "@eraconstructorpad", Integer.toString(expression.collapseSettings.eraPad)); - resultSql = StringUtils.replace(resultSql, "@inclusionRuleTable", getInclusionRuleTableSql(expression)); resultSql = StringUtils.replace(resultSql, "@inclusionImpactAnalysisByEventQuery", getInclusionAnalysisQuery("#qualified_events", 0)); resultSql = StringUtils.replace(resultSql, "@inclusionImpactAnalysisByPersonQuery", getInclusionAnalysisQuery("#best_events", 1)); - resultSql = StringUtils.replace(resultSql, "@cohortCensoredStatsQuery", (expression.censorWindow != null && (!StringUtils.isEmpty(expression.censorWindow.startDate) || !StringUtils.isEmpty(expression.censorWindow.endDate))) ? COHORT_CENSORED_STATS_TEMPLATE @@ -381,7 +489,10 @@ public String buildExpressionQuery(CohortExpression expression, BuildExpressionQ if (options.cohortId != null) { resultSql = StringUtils.replace(resultSql, "@target_cohort_id", options.cohortId.toString()); } - + if (options.resultCohortId != null) { + resultSql = StringUtils.replace(resultSql, "@result_cohort_id", options.resultCohortId.toString()); + } + resultSql = StringUtils.replace(resultSql, "@generateStats", options.generateStats ? "1" : "0"); if (options.cohortIdFieldName != null) { @@ -389,23 +500,80 @@ public String buildExpressionQuery(CohortExpression expression, BuildExpressionQ } else { resultSql = StringUtils.replaceAll(resultSql, "@cohort_id_field_name", DEFAULT_COHORT_ID_FIELD_NAME); } + resultSql = StringUtils.replace(resultSql, "@retain_cohort_covariates", options != null && options.retainCohortCovariates ? "1" : "0"); } else { resultSql = StringUtils.replaceAll(resultSql, "@cohort_id_field_name", DEFAULT_COHORT_ID_FIELD_NAME); } + + if (options != null && options.retainCohortCovariates) { + resultSql = StringUtils.replace(resultSql, "@concept_id", ", concept_id"); + resultSql = StringUtils.replace(resultSql, "@Qconcept_id", ", Q.concept_id"); + resultSql = StringUtils.replace(resultSql, "@pe_concept_id", ", pe.concept_id"); + + List allInclusionColumnsInserts = buildAllInclusionColumnsInserts(listField); + resultSql = StringUtils.replace(resultSql, "@allInclusionColumnsInserts", StringUtils.join(allInclusionColumnsInserts, " ")); + } else { + resultSql = StringUtils.replace(resultSql, "@conceptid", ""); + resultSql = StringUtils.replace(resultSql, "@concept_id", ""); + resultSql = StringUtils.replace(resultSql, "@Qconcept_id", ""); + resultSql = StringUtils.replace(resultSql, "@pe_concept_id", ""); + resultSql = StringUtils.replace(resultSql, "@allInclusionColumnsInserts", ""); + } + + return resultSql; } - - public String getCriteriaGroupQuery(CriteriaGroup group, String eventTable) { + + private List buildAllInclusionColumnsInserts(List> listField) { + List result = new ArrayList<>(); + listField.forEach(l -> { + if (l.size() > 0) { + String field = ""; + for (ColumnFieldData s : l) { + field = field + ", " + s.getName() + "_" + listField.indexOf(l); + } + result.add(field); + } + }); + return result; + } + + public String getCriteriaGroupQuery(CriteriaGroup group, String eventTable, boolean retainCohortCovariates) { String query = GROUP_QUERY_TEMPLATE; ArrayList additionalCriteriaQueries = new ArrayList<>(); String joinType = "INNER"; - + int indexId = 0; + // Add column field for group criteria needed to listField + Map mapDistinctField = new HashMap<>(); + for (int i = 0; i < group.criteriaList.length; i++) { + CorelatedCriteria cc = group.criteriaList[i]; + cc.criteria.getSelectedField(retainCohortCovariates).forEach(c -> { + mapDistinctField.put(c.getName(), c); + }); + } + + if (retainCohortCovariates) { + List selectColsG = new ArrayList<>(); + List selectColsCQ = new ArrayList<>(); + + for (Map.Entry entry : mapDistinctField.entrySet()) { + selectColsG.add(", G." + entry.getKey()); + selectColsCQ.add(", CQ." + entry.getKey()); + } + query = StringUtils.replace(query, "@e.additonColumns", StringUtils.join(selectColsCQ, "")); + query = StringUtils.replace(query, "@additonColumnsGroup", StringUtils.join(selectColsG, "")); + } else { + query = StringUtils.replace(query, "@e.additonColumns", ""); + query = StringUtils.replace(query, "@additonColumnsGroup", ""); + } + for (CorelatedCriteria cc : group.criteriaList) { - String acQuery = this.getCorelatedlCriteriaQuery(cc, eventTable); //ac.accept(this); - acQuery = StringUtils.replace(acQuery, "@indexId", "" + indexId); - additionalCriteriaQueries.add(acQuery); - indexId++; + cc.mapDistinctField = mapDistinctField; + String acQuery = this.getCorelatedlCriteriaQuery(cc, eventTable, retainCohortCovariates); // ac.accept(this); + acQuery = StringUtils.replace(acQuery, "@indexId", "" + indexId); + additionalCriteriaQueries.add(acQuery); + indexId++; } for (DemographicCriteria dc : group.demographicCriteriaList) { @@ -416,7 +584,7 @@ public String getCriteriaGroupQuery(CriteriaGroup group, String eventTable) { } for (CriteriaGroup g : group.groups) { - String gQuery = this.getCriteriaGroupQuery(g, eventTable); //g.accept(this); + String gQuery = this.getCriteriaGroupQuery(g, eventTable, retainCohortCovariates); //g.accept(this); gQuery = StringUtils.replace(gQuery, "@indexId", "" + indexId); additionalCriteriaQueries.add(gQuery); indexId++; @@ -462,9 +630,9 @@ public String getCriteriaGroupQuery(CriteriaGroup group, String eventTable) { return query; } - private String getInclusionRuleQuery(CriteriaGroup inclusionRule) { + private String getInclusionRuleQuery(CriteriaGroup inclusionRule, Boolean retainCohortCovariates) { 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"; + String additionalCriteriaQuery = "\nJOIN (\n" + getCriteriaGroupQuery(inclusionRule, "#qualified_events", retainCohortCovariates) + ") 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; @@ -521,7 +689,6 @@ public String getDemographicCriteriaQuery(DemographicCriteria criteria, String e } public String getWindowedCriteriaQuery(String sqlTemplate, WindowedCriteria criteria, String eventTable, BuilderOptions options) { - String query = sqlTemplate; boolean checkObservationPeriod = !criteria.ignoreObservationPeriod; @@ -534,6 +701,15 @@ public String getWindowedCriteriaQuery(String sqlTemplate, WindowedCriteria crit query = StringUtils.replace(query, "@additionalColumns", ""); } + if (options != null && options.isRetainCohortCovariates()) { + query = criteria.criteria.embedWindowedCriteriaQuery(query, criteria.mapDistinctField); + query = criteria.criteria.embedWindowedCriteriaQueryP(query); + } else { + query = StringUtils.replace(query, "@additionColumnscc", ""); + query = StringUtils.replace(query, "@additionGroupColumnscc", ""); + query = StringUtils.replace(query, "@p.additionColumns", ""); + } + // build index date window expression String startExpression; String endExpression; @@ -566,7 +742,7 @@ public String getWindowedCriteriaQuery(String sqlTemplate, WindowedCriteria crit clauses.add(String.format("%s <= %s", startEventDateExpression, endExpression)); } - // EndWindow + // EndWindow Window endWindow = criteria.endWindow; if (endWindow != null) { @@ -605,7 +781,7 @@ public String getWindowedCriteriaQuery(String sqlTemplate, WindowedCriteria crit return query; } - public String getWindowedCriteriaQuery(WindowedCriteria criteria, String eventTable) { + public String getWindowedCriteriaQuery(WindowedCriteria criteria, String eventTable) { String query = getWindowedCriteriaQuery(WINDOWED_CRITERIA_TEMPLATE, criteria, eventTable, null); return query; } @@ -615,7 +791,7 @@ public String getWindowedCriteriaQuery(WindowedCriteria criteria, String eventTa return query; } - public String getCorelatedlCriteriaQuery(CorelatedCriteria corelatedCriteria, String eventTable) { + public String getCorelatedlCriteriaQuery(CorelatedCriteria corelatedCriteria, String eventTable, Boolean retainCohortCovariates) { // pick the appropraite query template that is optimized for include (at least 1) or exclude (allow 0) String query = (corelatedCriteria.occurrence.type == Occurrence.AT_MOST || corelatedCriteria.occurrence.count == 0) ? ADDITIONAL_CRITERIA_LEFT_TEMPLATE : ADDITIONAL_CRITERIA_INNER_TEMPLATE; @@ -634,6 +810,8 @@ public String getCorelatedlCriteriaQuery(CorelatedCriteria corelatedCriteria, St } } + + builderOptions.setRetainCohortCovariates(retainCohortCovariates); query = getWindowedCriteriaQuery(query, corelatedCriteria, eventTable, builderOptions); // Occurrence criteria @@ -654,16 +832,16 @@ public String getCorelatedlCriteriaQuery(CorelatedCriteria corelatedCriteria, St protected String getCriteriaSql(CriteriaSqlBuilder builder, T criteria, BuilderOptions options) { String query = builder.getCriteriaSql(criteria, options); - return processCorrelatedCriteria(query, criteria); + return processCorrelatedCriteria(query, criteria, options); } protected String getCriteriaSql(CriteriaSqlBuilder builder, T criteria) { return this.getCriteriaSql(builder, criteria, null); } - protected String processCorrelatedCriteria(String query, Criteria criteria) { + protected String processCorrelatedCriteria(String query, Criteria criteria, BuilderOptions options) { if (criteria.CorrelatedCriteria != null && !criteria.CorrelatedCriteria.isEmpty()) { - query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria); + query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria, options, criteria); } return query; } @@ -761,16 +939,20 @@ private String getDateFieldForOffsetStrategy(DateOffsetStrategy.DateField dateFi } @Override - public String getStrategySql(DateOffsetStrategy strat, String eventTable) { + public String getStrategySql(DateOffsetStrategy strat, String eventTable, Boolean retainCohortCovariates) { 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)); - + if (retainCohortCovariates) { + strategySql = StringUtils.replace(strategySql, "@concept_id", ", concept_id"); + } else { + strategySql = StringUtils.replace(strategySql, "@concept_id", ""); + } return strategySql; } @Override - public String getStrategySql(CustomEraStrategy strat, String eventTable) { + public String getStrategySql(CustomEraStrategy strat, String eventTable, Boolean retainCohortCovariates) { if (strat.drugCodesetId == null) { throw new RuntimeException("Drug Codeset ID can not be NULL."); @@ -785,9 +967,12 @@ public String getStrategySql(CustomEraStrategy strat, String eventTable) { strategySql = StringUtils.replace(strategySql, "@gapDays", Integer.toString(strat.gapDays)); strategySql = StringUtils.replace(strategySql, "@offset", Integer.toString(strat.offset)); strategySql = StringUtils.replace(strategySql, "@drugExposureEndDateExpression", drugExposureEndDateExpression); - + if (retainCohortCovariates) { + strategySql = StringUtils.replace(strategySql, "@concept_id", ", concept_id"); + } else { + strategySql = StringUtils.replace(strategySql, "@concept_id", ""); + } return strategySql; } -// } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionEra.java b/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionEra.java index 368659ef..074e6931 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionEra.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionEra.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -61,4 +70,62 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option return dispatcher.getCriteriaSql(this, options); } + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (occurrenceCount != null) { + selectCols.add(new ColumnFieldData("condition_occurrence_count", ColumnFieldDataType.INTEGER)); + } + } + + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("condition_occurrence_count") && occurrenceCount != null) { + selectCols.add(", cc.condition_occurrence_count"); + groupCols.add(", cc.condition_occurrence_count"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (occurrenceCount != null) { + selectColsA.add(", A.condition_occurrence_count"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (occurrenceCount != null) { + selectCols.add(", Q.condition_occurrence_count"); + selectColsPE.add(", PE.condition_occurrence_count"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionOccurrence.java b/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionOccurrence.java index 5a60799e..026e192c 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionOccurrence.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionOccurrence.java @@ -20,7 +20,16 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeName; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -75,4 +84,113 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option { return dispatcher.getCriteriaSql(this, options); } + + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (conditionType != null && conditionType.length > 0) { + selectCols.add(new ColumnFieldData("condition_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (conditionSourceConcept != null) { + selectCols.add(new ColumnFieldData("condition_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(new ColumnFieldData("provider_id", ColumnFieldDataType.INTEGER)); + } + + if (conditionStatus != null && conditionStatus.length > 0) { + selectCols.add(new ColumnFieldData("condition_status_concept_id", ColumnFieldDataType.INTEGER)); + } + } + + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("condition_type_concept_id") && conditionType != null && conditionType.length > 0) { + selectCols.add(", cc.condition_type_concept_id"); + groupCols.add(", cc.condition_type_concept_id"); + } else if (entry.getKey().equals("condition_source_concept_id") && conditionSourceConcept != null) { + selectCols.add(", cc.condition_source_concept_id"); + groupCols.add(", cc.condition_source_concept_id"); + } else if (entry.getKey().equals("provider_id") && providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", cc.provider_id"); + groupCols.add(", cc.provider_id"); + } else if (entry.getKey().equals("condition_status_concept_id") && conditionStatus != null && conditionStatus.length > 0) { + selectCols.add(", cc.condition_status_concept_id"); + groupCols.add(", cc.condition_status_concept_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (conditionType != null && conditionType.length > 0) { + selectColsA.add(", A.condition_type_concept_id"); + } + + if (conditionSourceConcept != null) { + selectColsA.add(", A.condition_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectColsA.add(", A.provider_id"); + } + + if (conditionStatus != null && conditionStatus.length > 0) { + selectColsA.add(", A.condition_status_concept_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (conditionType != null && conditionType.length > 0) { + selectCols.add(", Q.condition_type_concept_id"); + selectColsPE.add(", PE.condition_type_concept_id"); + } + + if (conditionSourceConcept != null) { + selectCols.add(", Q.condition_source_concept_id"); + selectColsPE.add(", PE.condition_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", Q.provider_id"); + selectColsPE.add(", PE.provider_id"); + } + + if (conditionStatus != null && conditionStatus.length > 0) { + selectCols.add(", Q.condition_status_concept_id"); + selectColsPE.add(", PE.condition_status_concept_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/Criteria.java b/src/main/java/org/ohdsi/circe/cohortdefinition/Criteria.java index dc64997b..3e7b42f7 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/Criteria.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/Criteria.java @@ -22,7 +22,16 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; /** * @@ -54,6 +63,25 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher) { } public abstract String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions options); + + public List getSelectedField(Boolean retainCohortCovariates) { + return new ArrayList<>(); + } + + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + query = StringUtils.replace(query, "@additionColumnscc", ""); + return query; + } + + public String embedWindowedCriteriaQueryP(String query) { + query = StringUtils.replace(query, "@p.additionColumns", ""); + return query; + } + + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", ""); + return query; + } @JsonProperty("CorrelatedCriteria") public CriteriaGroup CorrelatedCriteria; diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/CustomEraStrategy.java b/src/main/java/org/ohdsi/circe/cohortdefinition/CustomEraStrategy.java index f585e73d..74d9b668 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/CustomEraStrategy.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/CustomEraStrategy.java @@ -39,7 +39,7 @@ public class CustomEraStrategy extends EndStrategy { public Integer daysSupplyOverride = null; @Override - public String accept(IGetEndStrategySqlDispatcher dispatcher, String eventTable) { - return dispatcher.getStrategySql(this, eventTable); + public String accept(IGetEndStrategySqlDispatcher dispatcher, String eventTable, Boolean retainCohortCovariates) { + return dispatcher.getStrategySql(this, eventTable, retainCohortCovariates); } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/DateOffsetStrategy.java b/src/main/java/org/ohdsi/circe/cohortdefinition/DateOffsetStrategy.java index 0ed6b8a8..c2f439ee 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/DateOffsetStrategy.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/DateOffsetStrategy.java @@ -38,7 +38,7 @@ public enum DateField { public int offset = 0; @Override - public String accept(IGetEndStrategySqlDispatcher dispatcher, String eventTable) { - return dispatcher.getStrategySql(this, eventTable); + public String accept(IGetEndStrategySqlDispatcher dispatcher, String eventTable, Boolean retainCohortCovariates) { + return dispatcher.getStrategySql(this, eventTable, retainCohortCovariates); } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/Death.java b/src/main/java/org/ohdsi/circe/cohortdefinition/Death.java index b3c3a366..7c738690 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/Death.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/Death.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -53,4 +62,92 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option return dispatcher.getCriteriaSql(this, options); } + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (occurrenceStartDate != null) { + selectCols.add(new ColumnFieldData("death_date", ColumnFieldDataType.DATE)); + } + + if (deathType != null && deathType.length > 0) { + selectCols.add(new ColumnFieldData("death_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (deathSourceConcept != null) { + selectCols.add(new ColumnFieldData("cause_concept_id", ColumnFieldDataType.INTEGER)); + } + } + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("death_date") && occurrenceStartDate != null) { + selectCols.add(", cc.death_date"); + groupCols.add(", cc.death_date"); + } else if (entry.getKey().equals("death_type_concept_id") && deathType != null && deathType.length > 0) { + selectCols.add(", cc.death_type_concept_id"); + groupCols.add(", cc.death_type_concept_id"); + } else if (entry.getKey().equals("cause_concept_id") && deathSourceConcept != null) { + selectCols.add(", cc.cause_concept_id"); + groupCols.add(", cc.cause_concept_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (occurrenceStartDate != null) { + selectColsA.add(", A.death_date"); + } + + if (deathType != null && deathType.length > 0) { + selectColsA.add(", A.death_type_concept_id"); + } + + if (deathSourceConcept != null) { + selectColsA.add(", A.cause_concept_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (occurrenceStartDate != null) { + selectCols.add(", Q.death_date"); + selectColsPE.add(", PE.death_date"); + } + + if (deathType != null && deathType.length > 0) { + selectCols.add(", Q.death_type_concept_id"); + selectColsPE.add(", PE.death_type_concept_id"); + } + + if (deathSourceConcept != null) { + selectCols.add(", Q.cause_concept_id"); + selectColsPE.add(", PE.cause_concept_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/DeviceExposure.java b/src/main/java/org/ohdsi/circe/cohortdefinition/DeviceExposure.java index c459ccee..086bd164 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/DeviceExposure.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/DeviceExposure.java @@ -19,7 +19,17 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -67,9 +77,141 @@ public class DeviceExposure extends Criteria { @JsonProperty("VisitType") public Concept[] visitType; + @JsonProperty("UnitConceptId") + public Concept[] unitConceptId; + @Override public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions options) { return dispatcher.getCriteriaSql(this, options); } - + + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (deviceType != null && deviceType.length > 0) { + selectCols.add(new ColumnFieldData("device_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (quantity != null) { + selectCols.add(new ColumnFieldData("quantity", ColumnFieldDataType.INTEGER)); + } + + if (uniqueDeviceId != null) { + selectCols.add(new ColumnFieldData("unique_device_id", ColumnFieldDataType.VARCHAR)); + } + + if (deviceSourceConcept != null) { + selectCols.add(new ColumnFieldData("device_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(new ColumnFieldData("provider_id", ColumnFieldDataType.INTEGER)); + } + } + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("device_type_concept_id") && deviceType != null && deviceType.length > 0) { + selectCols.add(", cc.device_type_concept_id"); + groupCols.add(", cc.device_type_concept_id"); + } else if (entry.getKey().equals("quantity") && quantity != null) { + selectCols.add(", cc.quantity"); + groupCols.add(", cc.quantity"); + } else if (entry.getKey().equals("unique_device_id") && uniqueDeviceId != null) { + selectCols.add(", cc.unique_device_id"); + groupCols.add(", cc.unique_device_id"); + } else if (entry.getKey().equals("device_source_concept_id") && deviceSourceConcept != null) { + selectCols.add(", cc.device_source_concept_id"); + groupCols.add(", cc.device_source_concept_id"); + } else if (entry.getKey().equals("provider_id") && providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", cc.provider_id"); + groupCols.add(", cc.provider_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (deviceType != null && deviceType.length > 0) { + selectColsA.add(", A.device_type_concept_id"); + } + + if (quantity != null) { + selectColsA.add(", A.quantity"); + } + + if (uniqueDeviceId != null) { + selectColsA.add(", A.unique_device_id"); + } + + if (deviceSourceConcept != null) { + selectColsA.add(", A.device_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectColsA.add(", A.provider_id"); + } + + // unit + if (unitConceptId != null && unitConceptId.length > 0) { + selectColsA.add(", A.unit_concept_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (deviceType != null && deviceType.length > 0) { + selectCols.add(", Q.device_type_concept_id"); + selectColsPE.add(", PE.device_type_concept_id"); + } + + if (quantity != null) { + selectCols.add(", Q.quantity"); + selectColsPE.add(", PE.quantity"); + } + + if (uniqueDeviceId != null) { + selectCols.add(", Q.unique_device_id"); + selectColsPE.add(", PE.unique_device_id"); + } + + if (deviceSourceConcept != null) { + selectCols.add(", Q.device_source_concept_id"); + selectColsPE.add(", PE.device_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", Q.provider_id"); + selectColsPE.add(", PE.provider_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/DoseEra.java b/src/main/java/org/ohdsi/circe/cohortdefinition/DoseEra.java index 34b2fc2c..a54f3c37 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/DoseEra.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/DoseEra.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -63,4 +72,112 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option return dispatcher.getCriteriaSql(this, options); } + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (eraStartDate != null) { + selectCols.add(new ColumnFieldData("dose_era_start_date", ColumnFieldDataType.DATE)); + } + + if (eraEndDate != null) { + selectCols.add(new ColumnFieldData("dose_era_end_date", ColumnFieldDataType.DATE)); + } + + // unit + if (unit != null && unit.length > 0) { + selectCols.add(new ColumnFieldData("unit_concept_id", ColumnFieldDataType.DATE)); + } + + if (doseValue != null) { + selectCols.add(new ColumnFieldData("dose_value", ColumnFieldDataType.NUMERIC)); + } + } + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("dose_era_start_date") && eraStartDate != null) { + selectCols.add(", cc.dose_era_start_date"); + groupCols.add(", cc.dose_era_start_date"); + } else if (entry.getKey().equals("dose_era_end_date") && eraEndDate != null) { + selectCols.add(", cc.dose_era_end_date"); + groupCols.add(", cc.dose_era_end_date"); + } else if (entry.getKey().equals("unit_concept_id") && unit != null && unit.length > 0) { + selectCols.add(", cc.unit_concept_id"); + groupCols.add(", cc.unit_concept_id"); + } else if (entry.getKey().equals("dose_value") && doseValue != null) { + selectCols.add(", cc.dose_value"); + groupCols.add(", cc.dose_value"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (eraStartDate != null) { + selectColsA.add(", A.dose_era_start_date"); + } + + if (eraEndDate != null) { + selectColsA.add(", A.dose_era_end_date"); + } + + // unit + if (unit != null && unit.length > 0) { + selectColsA.add(", A.unit_concept_id"); + } + + if (doseValue != null) { + selectColsA.add(", A.dose_value"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (eraStartDate != null) { + selectCols.add(", Q.dose_era_start_date"); + selectColsPE.add(", PE.dose_era_start_date"); + } + + if (eraEndDate != null) { + selectCols.add(", Q.dose_era_end_date"); + selectColsPE.add(", PE.dose_era_end_date"); + } + + // unit + if (unit != null && unit.length > 0) { + selectCols.add(", Q.unit_concept_id"); + selectColsPE.add(", PE.unit_concept_id"); + } + + if (doseValue != null) { + selectCols.add(", Q.dose_value"); + selectColsPE.add(", PE.dose_value"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/DrugEra.java b/src/main/java/org/ohdsi/circe/cohortdefinition/DrugEra.java index ad4c7773..fca8f5d6 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/DrugEra.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/DrugEra.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -63,4 +72,79 @@ public class DrugEra extends Criteria { public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions options) { return dispatcher.getCriteriaSql(this, options); } + + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (occurrenceCount != null) { + selectCols.add(new ColumnFieldData("drug_exposure_count", ColumnFieldDataType.INTEGER)); + } + + if (gapDays != null) { + selectCols.add(new ColumnFieldData("gap_days", ColumnFieldDataType.INTEGER)); + } + } + + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("drug_exposure_count") && occurrenceCount != null) { + selectCols.add(", cc.drug_exposure_count"); + groupCols.add(", cc.drug_exposure_count"); + } else if (entry.getKey().equals("gap_days") && gapDays != null) { + selectCols.add(", cc.gap_days"); + groupCols.add(", cc.gap_days"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (occurrenceCount != null) { + selectColsA.add(", A.drug_exposure_count"); + } + + if (gapDays != null) { + selectColsA.add(", A.gap_days"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (occurrenceCount != null) { + selectCols.add(", Q.drug_exposure_count"); + selectColsPE.add(", PE.drug_exposure_count"); + } + + if (gapDays != null) { + selectCols.add(", Q.gap_days"); + selectColsPE.add(", PE.gap_days"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/DrugExposure.java b/src/main/java/org/ohdsi/circe/cohortdefinition/DrugExposure.java index b1ce9c8c..e4f72cc6 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/DrugExposure.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/DrugExposure.java @@ -20,7 +20,16 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeName; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -90,5 +99,194 @@ public class DrugExposure extends Criteria { public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions options) { return dispatcher.getCriteriaSql(this, options); - } + } + + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (drugType != null && drugType.length > 0) { + selectCols.add(new ColumnFieldData("drug_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (stopReason != null) { + selectCols.add(new ColumnFieldData("stop_reason", ColumnFieldDataType.VARCHAR)); + } + + if (refills != null) { + selectCols.add(new ColumnFieldData("refills", ColumnFieldDataType.INTEGER)); + } + + if (quantity != null) { + selectCols.add(new ColumnFieldData("quantity", ColumnFieldDataType.INTEGER)); + } + + if (daysSupply != null) { + selectCols.add(new ColumnFieldData("days_supply", ColumnFieldDataType.INTEGER)); + } + + if (routeConcept != null && routeConcept.length > 0) { + selectCols.add(new ColumnFieldData("route_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (lotNumber != null) { + selectCols.add(new ColumnFieldData("lot_number", ColumnFieldDataType.VARCHAR)); + } + + if (drugSourceConcept != null) { + selectCols.add(new ColumnFieldData("drug_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(new ColumnFieldData("provider_id", ColumnFieldDataType.INTEGER)); + } + } + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("drug_type_concept_id") && drugType != null && drugType.length > 0) { + selectCols.add(", cc.drug_type_concept_id"); + groupCols.add(", cc.drug_type_concept_id"); + } else if (entry.getKey().equals("stop_reason") && stopReason != null) { + selectCols.add(", cc.stop_reason"); + groupCols.add(", cc.stop_reason"); + } else if (entry.getKey().equals("refills") && refills != null) { + selectCols.add(", cc.refills"); + groupCols.add(", cc.refills"); + } else if (entry.getKey().equals("quantity") && quantity != null) { + selectCols.add(", cc.quantity"); + groupCols.add(", cc.quantity"); + } else if (entry.getKey().equals("days_supply") && daysSupply != null) { + selectCols.add(", cc.days_supply"); + groupCols.add(", cc.days_supply"); + } else if (entry.getKey().equals("route_concept_id") && routeConcept != null && routeConcept.length > 0) { + selectCols.add(", cc.route_concept_id"); + groupCols.add(", cc.route_concept_id"); + } else if (entry.getKey().equals("lot_number") && lotNumber != null) { + selectCols.add(", cc.lot_number"); + groupCols.add(", cc.lot_number"); + } else if (entry.getKey().equals("drug_source_concept_id") && drugSourceConcept != null) { + selectCols.add(", cc.drug_source_concept_id"); + groupCols.add(", cc.drug_source_concept_id"); + } else if (entry.getKey().equals("provider_id") && providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", cc.provider_id"); + groupCols.add(", cc.provider_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (drugType != null && drugType.length > 0) { + selectColsA.add(", A.drug_type_concept_id"); + } + + if (stopReason != null) { + selectColsA.add(", A.stop_reason"); + } + + if (refills != null) { + selectColsA.add(", A.refills"); + } + + if (quantity != null) { + selectColsA.add(", A.quantity"); + } + + if (daysSupply != null) { + selectColsA.add(", A.days_supply"); + } + + if (routeConcept != null && routeConcept.length > 0) { + selectColsA.add(", A.route_concept_id"); + } + + if (lotNumber != null) { + selectColsA.add(", A.lot_number"); + } + + if (drugSourceConcept != null) { + selectColsA.add(", A.drug_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectColsA.add(", A.provider_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (drugType != null && drugType.length > 0) { + selectCols.add(", Q.drug_type_concept_id"); + selectColsPE.add(", PE.drug_type_concept_id"); + } + + if (stopReason != null) { + selectCols.add(", Q.stop_reason"); + selectColsPE.add(", PE.stop_reason"); + } + + if (refills != null) { + selectCols.add(", Q.refills"); + selectColsPE.add(", PE.refills"); + } + + if (quantity != null) { + selectCols.add(", Q.quantity"); + selectColsPE.add(", PE.quantity"); + } + + if (daysSupply != null) { + selectCols.add(", Q.days_supply"); + selectColsPE.add(", PE.days_supply"); + } + + if (routeConcept != null && routeConcept.length > 0) { + selectCols.add(", Q.route_concept_id"); + selectColsPE.add(", PE.route_concept_id"); + } + + if (lotNumber != null) { + selectCols.add(", Q.lot_number"); + selectColsPE.add(", PE.lot_number"); + } + + if (drugSourceConcept != null) { + selectCols.add(", Q.drug_source_concept_id"); + selectColsPE.add(", PE.drug_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", Q.provider_id"); + selectColsPE.add(", PE.provider_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/EndStrategy.java b/src/main/java/org/ohdsi/circe/cohortdefinition/EndStrategy.java index 57f08bc4..a7ea9042 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/EndStrategy.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/EndStrategy.java @@ -32,5 +32,5 @@ @JsonSubTypes.Type(value = CustomEraStrategy.class, name = "CustomEra") }) public abstract class EndStrategy { - public abstract String accept(IGetEndStrategySqlDispatcher dispatcher, String eventTable); + public abstract String accept(IGetEndStrategySqlDispatcher dispatcher, String eventTable, Boolean retainCohortCovariates); } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/IGetEndStrategySqlDispatcher.java b/src/main/java/org/ohdsi/circe/cohortdefinition/IGetEndStrategySqlDispatcher.java index 15e4c6ee..405c95df 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/IGetEndStrategySqlDispatcher.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/IGetEndStrategySqlDispatcher.java @@ -23,6 +23,6 @@ * @author Chris Knoll */ interface IGetEndStrategySqlDispatcher { - public String getStrategySql(DateOffsetStrategy strategy, String eventTable); - public String getStrategySql(CustomEraStrategy strategy, String eventTable); + public String getStrategySql(DateOffsetStrategy strategy, String eventTable, Boolean retainCohortCovariates); + public String getStrategySql(CustomEraStrategy strategy, String eventTable, Boolean retainCohortCovariates); } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/Measurement.java b/src/main/java/org/ohdsi/circe/cohortdefinition/Measurement.java index f27504ea..e20cd724 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/Measurement.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/Measurement.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -91,5 +100,180 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option return dispatcher.getCriteriaSql(this, options); } + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + selectCols.add(new ColumnFieldData("value_as_number", ColumnFieldDataType.NUMERIC)); + + if (valueAsConcept != null && valueAsConcept.length > 0) { + selectCols.add(new ColumnFieldData("value_as_concept_id", ColumnFieldDataType.INTEGER)); + } + // unit + if (unit != null && unit.length > 0) { + selectCols.add(new ColumnFieldData("unit_concept_id", ColumnFieldDataType.INTEGER)); + } + // range_low + if (rangeLow != null) { + selectCols.add(new ColumnFieldData("range_low", ColumnFieldDataType.NUMERIC)); + } + + // range_high + if (rangeHigh != null) { + selectCols.add(new ColumnFieldData("range_high", ColumnFieldDataType.NUMERIC)); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(new ColumnFieldData("provider_id", ColumnFieldDataType.INTEGER)); + } + + // measurementType + if (measurementType != null && measurementType.length > 0) { + selectCols.add(new ColumnFieldData("measurement_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + // operator + if (operator != null && operator.length > 0) { + selectCols.add(new ColumnFieldData("operator_concept_id", ColumnFieldDataType.INTEGER)); + } + } + + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("value_as_number")) { + selectCols.add(", cc.value_as_number"); + groupCols.add(", cc.value_as_number"); + } else if (entry.getKey().equals("value_as_concept_id") && valueAsConcept != null && valueAsConcept.length > 0) { + selectCols.add(", cc.value_as_concept_id"); + groupCols.add(", cc.value_as_concept_id"); + } else if (entry.getKey().equals("unit_concept_id") && unit != null && unit.length > 0) { + selectCols.add(", cc.unit_concept_id"); + groupCols.add(", cc.unit_concept_id"); + } else if (entry.getKey().equals("range_low") && rangeLow != null) { + selectCols.add(", cc.range_low"); + groupCols.add(", cc.range_low"); + } else if (entry.getKey().equals("range_high") && rangeHigh != null) { + selectCols.add(", cc.range_high"); + groupCols.add(", cc.range_high"); + } else if (entry.getKey().equals("provider_id") && providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", cc.provider_id"); + groupCols.add(", cc.provider_id"); + } else if (entry.getKey().equals("measurement_type_concept_id") && measurementType != null && measurementType.length > 0) { + selectCols.add(", cc.measurement_type_concept_id"); + groupCols.add(", cc.measurement_type_concept_id"); + } else if (entry.getKey().equals("operator_concept_id") && operator != null && operator.length > 0) { + selectCols.add(", cc.operator_concept_id"); + groupCols.add(", cc.operator_concept_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + selectColsA.add(", A.value_as_number"); + if (valueAsConcept != null && valueAsConcept.length > 0) { + selectColsA.add(", A.value_as_concept_id"); + } + + // unit + if (unit != null && unit.length > 0) { + selectColsA.add(", A.unit_concept_id"); + } + + // range_low + if (rangeLow != null) { + selectColsA.add(", A.range_low"); + } + + // range_high + if (rangeHigh != null) { + selectColsA.add(", A.range_high"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectColsA.add(", A.provider_id"); + } + + // measurementType + if (measurementType != null && measurementType.length > 0) { + selectColsA.add(", A.measurement_type_concept_id"); + } + + // operator + if (operator != null && operator.length > 0) { + selectColsA.add(", A.operator_concept_id"); + } + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + if(!options.isPrimaryCriteria()){ + selectCols.add(", Q.value_as_number"); + selectColsPE.add(", PE.value_as_number"); + + if (valueAsConcept != null && valueAsConcept.length > 0) { + selectCols.add(", Q.value_as_concept_id"); + selectColsPE.add(", PE.value_as_concept_id"); + } + + // unit + if (unit != null && unit.length > 0) { + selectCols.add(", Q.unit_concept_id"); + selectColsPE.add(", PE.unit_concept_id"); + } + + // range_low + if (rangeLow != null) { + selectCols.add(", Q.range_low"); + selectColsPE.add(", PE.range_low"); + } + + // range_high + if (rangeHigh != null) { + selectCols.add(", Q.range_high"); + selectColsPE.add(", PE.range_high"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", Q.provider_id"); + selectColsPE.add(", PE.provider_id"); + } + + // measurementType + if (measurementType != null && measurementType.length > 0) { + selectCols.add(", Q.measurement_type_concept_id"); + selectColsPE.add(", PE.measurement_type_concept_id"); + } + + // operator + if (operator != null && operator.length > 0) { + selectCols.add(", Q.operator_concept_id"); + selectColsPE.add(", PE.operator_concept_id"); + } + } + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/Observation.java b/src/main/java/org/ohdsi/circe/cohortdefinition/Observation.java index 04c8bfd4..65a35d70 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/Observation.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/Observation.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -78,4 +87,159 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option { return dispatcher.getCriteriaSql(this, options); } + + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + selectCols.add(new ColumnFieldData("value_as_number", ColumnFieldDataType.NUMERIC)); + + // observationType + if (observationType != null && observationType.length > 0) { + selectCols.add(new ColumnFieldData("observation_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (valueAsString != null) { + selectCols.add(new ColumnFieldData("value_as_string", ColumnFieldDataType.VARCHAR)); + } + + if (valueAsConcept != null && valueAsConcept.length > 0) { + selectCols.add(new ColumnFieldData("value_as_concept_id", ColumnFieldDataType.INTEGER)); + } + // unit + if (unit != null && unit.length > 0) { + selectCols.add(new ColumnFieldData("unit_concept_id", ColumnFieldDataType.INTEGER)); + } + + // qualifier + if (qualifier != null && qualifier.length > 0) { + selectCols.add(new ColumnFieldData("qualifier_concept_id", ColumnFieldDataType.INTEGER)); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(new ColumnFieldData("provider_id", ColumnFieldDataType.INTEGER)); + } + } + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("value_as_number")) { + selectCols.add(", cc.value_as_number"); + groupCols.add(", cc.value_as_number"); + } else if (entry.getKey().equals("observation_type_concept_id") && observationType != null && observationType.length > 0) { + selectCols.add(", cc.observation_type_concept_id"); + groupCols.add(", cc.observation_type_concept_id"); + } else if (entry.getKey().equals("value_as_string") && valueAsString != null) { + selectCols.add(", cc.value_as_string"); + groupCols.add(", cc.value_as_string"); + } else if (entry.getKey().equals("value_as_concept_id") && valueAsConcept != null && valueAsConcept.length > 0) { + selectCols.add(", cc.value_as_concept_id"); + groupCols.add(", cc.value_as_concept_id"); + } else if (entry.getKey().equals("unit_concept_id") && unit != null && unit.length > 0) { + selectCols.add(", cc.unit_concept_id"); + groupCols.add(", cc.unit_concept_id"); + } else if (entry.getKey().equals("qualifier_concept_id") && qualifier != null && qualifier.length > 0) { + selectCols.add(", cc.qualifier_concept_id"); + groupCols.add(", cc.qualifier_concept_id"); + } else if (entry.getKey().equals("provider_id") && providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", cc.provider_id"); + groupCols.add(", cc.provider_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + selectColsA.add(", A.value_as_number"); + // observationType + if (observationType != null && observationType.length > 0) { + selectColsA.add(", A.observation_type_concept_id"); + } + + if (valueAsString != null) { + selectColsA.add(", A.value_as_string"); + } + + if (valueAsConcept != null && valueAsConcept.length > 0) { + selectColsA.add(", A.value_as_concept_id"); + } + // unit + if (unit != null && unit.length > 0) { + selectColsA.add(", A.unit_concept_id"); + } + + // qualifier + if (qualifier != null && qualifier.length > 0) { + selectColsA.add(", A.qualifier_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectColsA.add(", A.provider_id"); + } + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + selectCols.add(", Q.value_as_number"); + selectColsPE.add(", PE.value_as_number"); + + // observationType + if (observationType != null && observationType.length > 0) { + selectCols.add(", Q.observation_type_concept_id"); + selectColsPE.add(", PE.observation_type_concept_id"); + } + + if (valueAsString != null) { + selectCols.add(", Q.value_as_string"); + selectColsPE.add(", PE.value_as_string"); + } + + if (valueAsConcept != null && valueAsConcept.length > 0) { + selectCols.add(", Q.value_as_concept_id"); + selectColsPE.add(", PE.value_as_concept_id"); + } + // unit + if (unit != null && unit.length > 0) { + selectCols.add(", Q.unit_concept_id"); + selectColsPE.add(", PE.unit_concept_id"); + } + + // qualifier + if (qualifier != null && qualifier.length > 0) { + selectCols.add(", Q.qualifier_concept_id"); + selectColsPE.add(", PE.qualifier_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", Q.provider_id"); + selectColsPE.add(", PE.provider_id"); + } + } + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } + + } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/ObservationPeriod.java b/src/main/java/org/ohdsi/circe/cohortdefinition/ObservationPeriod.java index 28a5824d..e498c805 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/ObservationPeriod.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/ObservationPeriod.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -57,4 +66,63 @@ public class ObservationPeriod extends Criteria { public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions options) { return dispatcher.getCriteriaSql(this, options); } + + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (periodType != null && periodType.length > 0) { + selectCols.add(new ColumnFieldData("period_type_concept_id", ColumnFieldDataType.INTEGER)); + } + } + + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("period_type_concept_id") && periodType != null && periodType.length > 0) { + selectCols.add(", cc.period_type_concept_id"); + groupCols.add(", cc.period_type_concept_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (periodType != null && periodType.length > 0) { + selectColsA.add(", A.period_type_concept_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (periodType != null && periodType.length > 0) { + selectCols.add(", Q.period_type_concept_id"); + selectColsPE.add(", PE.period_type_concept_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/PayerPlanPeriod.java b/src/main/java/org/ohdsi/circe/cohortdefinition/PayerPlanPeriod.java index dd7a2b36..2b1ba2f2 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/PayerPlanPeriod.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/PayerPlanPeriod.java @@ -19,8 +19,17 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.analysis.versioning.CdmVersion; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; @CdmVersion(range = ">=5.3") @@ -77,4 +86,211 @@ public class PayerPlanPeriod extends Criteria { public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions options) { return dispatcher.getCriteriaSql(this, options); } + + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (periodStartDate != null) { + selectCols.add(new ColumnFieldData("payer_plan_period_start_date", ColumnFieldDataType.DATE)); + } + + if (periodEndDate != null) { + selectCols.add(new ColumnFieldData("payer_plan_period_end_date", ColumnFieldDataType.DATE)); + } + + if (payerConcept != null) { + selectCols.add(new ColumnFieldData("payer_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (planConcept != null) { + selectCols.add(new ColumnFieldData("plan_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (sponsorConcept != null) { + selectCols.add(new ColumnFieldData("sponsor_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (stopReasonConcept != null) { + selectCols.add(new ColumnFieldData("stop_reason_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (payerSourceConcept != null) { + selectCols.add(new ColumnFieldData("payer_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (planSourceConcept != null) { + selectCols.add(new ColumnFieldData("plan_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (sponsorSourceConcept != null) { + selectCols.add(new ColumnFieldData("sponsor_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (stopReasonSourceConcept != null) { + selectCols.add(new ColumnFieldData("stop_reason_source_concept_id", ColumnFieldDataType.INTEGER)); + } + } + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("payer_plan_period_start_date") && periodStartDate != null) { + selectCols.add(", cc.payer_plan_period_start_date"); + groupCols.add(", cc.payer_plan_period_start_date"); + } else if (entry.getKey().equals("payer_plan_period_end_date") && periodEndDate != null) { + selectCols.add(", cc.payer_plan_period_end_date"); + groupCols.add(", cc.payer_plan_period_end_date"); + } else if (entry.getKey().equals("payer_concept_id") && payerConcept != null) { + selectCols.add(", cc.payer_concept_id"); + groupCols.add(", cc.payer_concept_id"); + } else if (entry.getKey().equals("plan_concept_id") && planConcept != null) { + selectCols.add(", cc.plan_concept_id"); + groupCols.add(", cc.plan_concept_id"); + } else if (entry.getKey().equals("sponsor_concept_id") && sponsorConcept != null) { + selectCols.add(", cc.sponsor_concept_id"); + groupCols.add(", cc.sponsor_concept_id"); + } else if (entry.getKey().equals("stop_reason_concept_id") && stopReasonConcept != null) { + selectCols.add(", cc.stop_reason_concept_id"); + groupCols.add(", cc.stop_reason_concept_id"); + } else if (entry.getKey().equals("payer_source_concept_id") && payerSourceConcept != null) { + selectCols.add(", cc.payer_source_concept_id"); + groupCols.add(", cc.payer_source_concept_id"); + } else if (entry.getKey().equals("plan_source_concept_id") && planSourceConcept != null) { + selectCols.add(", cc.plan_source_concept_id"); + groupCols.add(", cc.plan_source_concept_id"); + } else if (entry.getKey().equals("sponsor_source_concept_id") && sponsorSourceConcept != null) { + selectCols.add(", cc.sponsor_source_concept_id"); + groupCols.add(", cc.sponsor_source_concept_id"); + } else if (entry.getKey().equals("stop_reason_source_concept_id") && stopReasonSourceConcept != null) { + selectCols.add(", cc.stop_reason_source_concept_id"); + groupCols.add(", cc.stop_reason_source_concept_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (periodStartDate != null) { + selectColsA.add(", A.payer_plan_period_start_date"); + } + + if (periodEndDate != null) { + selectColsA.add(", A.payer_plan_period_end_date"); + } + + if (payerConcept != null) { + selectColsA.add(", A.payer_concept_id"); + } + + if (planConcept != null) { + selectColsA.add(", A.plan_concept_id"); + } + + if (sponsorConcept != null) { + selectColsA.add(", A.sponsor_concept_id"); + } + + if (stopReasonConcept != null) { + selectColsA.add(", A.stop_reason_concept_id"); + } + + if (payerSourceConcept != null) { + selectColsA.add(", A.payer_source_concept_id"); + } + + if (planSourceConcept != null) { + selectColsA.add(", A.plan_source_concept_id"); + } + + if (sponsorSourceConcept != null) { + selectColsA.add(", A.sponsor_source_concept_id"); + } + + if (stopReasonSourceConcept != null) { + selectColsA.add(", A.stop_reason_source_concept_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (periodStartDate != null) { + selectCols.add(", Q.payer_plan_period_start_date"); + selectColsPE.add(", PE.payer_plan_period_start_date"); + } + + if (periodEndDate != null) { + selectCols.add(", Q.payer_plan_period_end_date"); + selectColsPE.add(", PE.payer_plan_period_end_date"); + } + + if (payerConcept != null) { + selectCols.add(", Q.payer_concept_id"); + selectColsPE.add(", PE.payer_concept_id"); + } + + if (planConcept != null) { + selectCols.add(", Q.plan_concept_id"); + selectColsPE.add(", PE.plan_concept_id"); + } + + if (sponsorConcept != null) { + selectCols.add(", Q.sponsor_concept_id"); + selectColsPE.add(", PE.sponsor_concept_id"); + } + + if (stopReasonConcept != null) { + selectCols.add(", Q.stop_reason_concept_id"); + selectColsPE.add(", PE.stop_reason_concept_id"); + } + + if (stopReasonConcept != null) { + selectCols.add(", Q.stop_reason_concept_id"); + selectColsPE.add(", PE.stop_reason_concept_id"); + } + + if (payerSourceConcept != null) { + selectCols.add(", Q.payer_source_concept_id"); + selectColsPE.add(", PE.payer_source_concept_id"); + } + + if (planSourceConcept != null) { + selectCols.add(", Q.plan_source_concept_id"); + selectColsPE.add(", PE.plan_source_concept_id"); + } + + if (sponsorSourceConcept != null) { + selectCols.add(", Q.sponsor_source_concept_id"); + selectColsPE.add(", PE.sponsor_source_concept_id"); + } + + if (stopReasonSourceConcept != null) { + selectCols.add(", Q.stop_reason_source_concept_id"); + selectColsPE.add(", PE.stop_reason_source_concept_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/ProcedureOccurrence.java b/src/main/java/org/ohdsi/circe/cohortdefinition/ProcedureOccurrence.java index feb4c314..661eb3b4 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/ProcedureOccurrence.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/ProcedureOccurrence.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -69,4 +78,130 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option return dispatcher.getCriteriaSql(this, options); } + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (procedureType != null && procedureType.length > 0) { + selectCols.add(new ColumnFieldData("procedure_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (modifier != null && modifier.length > 0) { + selectCols.add(new ColumnFieldData("modifier_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (quantity != null) { + selectCols.add(new ColumnFieldData("quantity", ColumnFieldDataType.INTEGER)); + } + + if (procedureSourceConcept != null) { + selectCols.add(new ColumnFieldData("procedure_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(new ColumnFieldData("provider_id", ColumnFieldDataType.INTEGER)); + } + } + + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("procedure_type_concept_id") && procedureType != null && procedureType.length > 0) { + selectCols.add(", cc.procedure_type_concept_id"); + groupCols.add(", cc.procedure_type_concept_id"); + } else if (entry.getKey().equals("modifier_concept_id") && modifier != null && modifier.length > 0) { + selectCols.add(", cc.modifier_concept_id"); + groupCols.add(", cc.modifier_concept_id"); + } else if (entry.getKey().equals("quantity") && quantity != null) { + selectCols.add(", cc.quantity"); + groupCols.add(", cc.quantity"); + } else if (entry.getKey().equals("procedure_source_concept_id") && procedureSourceConcept != null) { + selectCols.add(", cc.procedure_source_concept_id"); + groupCols.add(", cc.procedure_source_concept_id"); + } else if (entry.getKey().equals("provider_id") && providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", cc.provider_id"); + groupCols.add(", cc.provider_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (procedureType != null && procedureType.length > 0) { + selectColsA.add(", A.procedure_type_concept_id"); + } + + if (modifier != null && modifier.length > 0) { + selectColsA.add(", A.modifier_concept_id"); + } + + if (quantity != null) { + selectColsA.add(", A.quantity"); + } + + if (procedureSourceConcept != null) { + selectColsA.add(", A.procedure_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectColsA.add(", A.provider_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (procedureType != null && procedureType.length > 0) { + selectCols.add(", Q.procedure_type_concept_id"); + selectColsPE.add(", PE.procedure_type_concept_id"); + } + + if (modifier != null && modifier.length > 0) { + selectCols.add(", Q.modifier_concept_id"); + selectColsPE.add(", PE.modifier_concept_id"); + } + + if (quantity != null) { + selectCols.add(", Q.quantity"); + selectColsPE.add(", PE.quantity"); + } + + if (procedureSourceConcept != null) { + selectCols.add(", Q.procedure_source_concept_id"); + selectColsPE.add(", PE.procedure_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", Q.provider_id"); + selectColsPE.add(", PE.provider_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/Specimen.java b/src/main/java/org/ohdsi/circe/cohortdefinition/Specimen.java index ce8aa9ad..9bb90acb 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/Specimen.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/Specimen.java @@ -19,7 +19,16 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -73,4 +82,156 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option return dispatcher.getCriteriaSql(this, options); } + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (occurrenceStartDate != null) { + selectCols.add(new ColumnFieldData("specimen_date", ColumnFieldDataType.DATE)); + } + + if (specimenType != null && specimenType.length > 0) { + selectCols.add(new ColumnFieldData("specimen_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (unit != null && unit.length > 0) { + selectCols.add(new ColumnFieldData("unit_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (quantity != null) { + selectCols.add(new ColumnFieldData("quantity", ColumnFieldDataType.INTEGER)); + } + + if (anatomicSite != null && anatomicSite.length > 0) { + selectCols.add(new ColumnFieldData("anatomic_site_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (diseaseStatus != null && diseaseStatus.length > 0) { + selectCols.add(new ColumnFieldData("disease_status_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (sourceId != null) { + selectCols.add(new ColumnFieldData("specimen_source_id", ColumnFieldDataType.VARCHAR)); + } + } + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("specimen_date") && occurrenceStartDate != null) { + selectCols.add(", cc.specimen_date"); + groupCols.add(", cc.specimen_date"); + } else if (entry.getKey().equals("specimen_type_concept_id") && specimenType != null && specimenType.length > 0) { + selectCols.add(", cc.specimen_type_concept_id"); + groupCols.add(", cc.specimen_type_concept_id"); + } else if (entry.getKey().equals("unit_concept_id") && unit != null && unit.length > 0) { + selectCols.add(", cc.unit_concept_id"); + groupCols.add(", cc.unit_concept_id"); + } else if (entry.getKey().equals("quantity") && quantity != null) { + selectCols.add(", cc.quantity"); + groupCols.add(", cc.quantity"); + } else if (entry.getKey().equals("anatomic_site_concept_id") && anatomicSite != null && anatomicSite.length > 0) { + selectCols.add(", cc.anatomic_site_concept_id"); + groupCols.add(", cc.anatomic_site_concept_id"); + } else if (entry.getKey().equals("disease_status_concept_id") && diseaseStatus != null && diseaseStatus.length > 0) { + selectCols.add(", cc.disease_status_concept_id"); + groupCols.add(", cc.disease_status_concept_id"); + } else if (entry.getKey().equals("specimen_source_id") && sourceId != null) { + selectCols.add(", cc.specimen_source_id"); + groupCols.add(", cc.specimen_source_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (occurrenceStartDate != null) { + selectColsA.add(", A.specimen_date"); + } + + if (specimenType != null && specimenType.length > 0) { + selectColsA.add(", A.specimen_type_concept_id"); + } + + if (unit != null && unit.length > 0) { + selectColsA.add(", A.unit_concept_id"); + } + + if (quantity != null) { + selectColsA.add(", A.quantity"); + } + + if (anatomicSite != null && anatomicSite.length > 0) { + selectColsA.add(", A.anatomic_site_concept_id"); + } + + if (diseaseStatus != null && diseaseStatus.length > 0) { + selectColsA.add(", A.disease_status_concept_id"); + } + + if (sourceId != null) { + selectColsA.add(", A.specimen_source_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (occurrenceStartDate != null) { + selectCols.add(", Q.specimen_date"); + selectColsPE.add(", PE.specimen_date"); + } + + if (specimenType != null && specimenType.length > 0) { + selectCols.add(", Q.specimen_type_concept_id"); + selectColsPE.add(", PE.specimen_type_concept_id"); + } + + if (unit != null && unit.length > 0) { + selectCols.add(", Q.unit_concept_id"); + selectColsPE.add(", PE.unit_concept_id"); + } + + if (quantity != null) { + selectCols.add(", Q.quantity"); + selectColsPE.add(", PE.quantity"); + } + + if (anatomicSite != null && anatomicSite.length > 0) { + selectCols.add(", Q.anatomic_site_concept_id"); + selectColsPE.add(", PE.anatomic_site_concept_id"); + } + + if (diseaseStatus != null && diseaseStatus.length > 0) { + selectCols.add(", Q.disease_status_concept_id"); + selectColsPE.add(", PE.disease_status_concept_id"); + } + + if (sourceId != null) { + selectCols.add(", Q.specimen_source_id"); + selectColsPE.add(", PE.specimen_source_id"); + } + } + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/VisitDetail.java b/src/main/java/org/ohdsi/circe/cohortdefinition/VisitDetail.java index 3b7859c2..5034b8cc 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/VisitDetail.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/VisitDetail.java @@ -19,9 +19,17 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.analysis.versioning.CdmVersion; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; -import org.ohdsi.circe.vocabulary.Concept; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; /** * @@ -77,5 +85,126 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option return dispatcher.getCriteriaSql(this, options); } + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (visitDetailStartDate != null) { + selectCols.add(new ColumnFieldData("visit_detail_start_date", ColumnFieldDataType.DATE)); + } + + if (visitDetailEndDate != null) { + selectCols.add(new ColumnFieldData("visit_detail_end_date", ColumnFieldDataType.DATE)); + } + + if (visitDetailTypeCS != null) { + selectCols.add(new ColumnFieldData("visit_detail_type_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (visitDetailSourceConcept != null) { + selectCols.add(new ColumnFieldData("visit_detail_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + if (providerSpecialtyCS != null) { + selectCols.add(new ColumnFieldData("provider_id", ColumnFieldDataType.INTEGER)); + } + } + + return selectCols; + } + + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("visit_detail_start_date") && visitDetailStartDate != null) { + selectCols.add(", cc.visit_detail_start_date"); + groupCols.add(", cc.visit_detail_start_date"); + } else if (entry.getKey().equals("visit_detail_end_date") && visitDetailEndDate != null) { + selectCols.add(", cc.visit_detail_end_date"); + groupCols.add(", cc.visit_detail_end_date"); + } else if (entry.getKey().equals("visit_detail_type_concept_id") && visitDetailTypeCS != null) { + selectCols.add(", cc.visit_detail_type_concept_id"); + groupCols.add(", cc.visit_detail_type_concept_id"); + } else if (entry.getKey().equals("visit_detail_source_concept_id") && visitDetailSourceConcept != null) { + selectCols.add(", cc.visit_detail_source_concept_id"); + groupCols.add(", cc.visit_detail_source_concept_id"); + } else if (entry.getKey().equals("provider_id") && providerSpecialtyCS != null) { + selectCols.add(", cc.provider_id"); + groupCols.add(", cc.provider_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (visitDetailStartDate != null) { + selectColsA.add(", A.visit_detail_start_date"); + } + + if (visitDetailEndDate != null) { + selectColsA.add(", A.visit_detail_end_date"); + } + + if (visitDetailTypeCS != null) { + selectColsA.add(", A.visit_detail_type_concept_id"); + } + + if (visitDetailSourceConcept != null) { + selectColsA.add(", A.visit_detail_source_concept_id"); + } + + if (providerSpecialtyCS != null) { + selectColsA.add(", A.provider_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (visitDetailStartDate != null) { + selectCols.add(", Q.visit_detail_start_date"); + selectColsPE.add(", PE.visit_detail_start_date"); + } + + if (visitDetailEndDate != null) { + selectCols.add(", Q.visit_detail_end_date"); + selectColsPE.add(", PE.visit_detail_end_date"); + } + + if (visitDetailTypeCS != null) { + selectCols.add(", Q.visit_detail_type_concept_id"); + selectColsPE.add(", PE.visit_detail_type_concept_id"); + } + + if (visitDetailSourceConcept != null) { + selectCols.add(", Q.visit_detail_source_concept_id"); + selectColsPE.add(", PE.visit_detail_source_concept_id"); + } + + if (providerSpecialtyCS != null) { + selectCols.add(", Q.provider_id"); + selectColsPE.add(", PE.provider_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/VisitOccurrence.java b/src/main/java/org/ohdsi/circe/cohortdefinition/VisitOccurrence.java index f38d46b0..b2353bb3 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/VisitOccurrence.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/VisitOccurrence.java @@ -19,8 +19,17 @@ package org.ohdsi.circe.cohortdefinition; import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; import org.ohdsi.analysis.versioning.CdmVersion; import org.ohdsi.circe.cohortdefinition.builders.BuilderOptions; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldDataType; import org.ohdsi.circe.vocabulary.Concept; /** @@ -80,5 +89,81 @@ public String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions option return dispatcher.getCriteriaSql(this, options); } + @Override + public List getSelectedField(Boolean retainCohortCovariates) { + List selectCols = new ArrayList<>(); + + if (retainCohortCovariates) { + if (visitSourceConcept != null) { + selectCols.add(new ColumnFieldData("visit_source_concept_id", ColumnFieldDataType.INTEGER)); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(new ColumnFieldData("provider_id", ColumnFieldDataType.INTEGER)); + } + } + + return selectCols; + } + @Override + public String embedWindowedCriteriaQuery(String query, Map mapDistinctField) { + List selectCols = new ArrayList<>(); + List groupCols = new ArrayList<>(); + + for (Entry entry : mapDistinctField.entrySet()) { + if (entry.getKey().equals("visit_source_concept_id") && visitSourceConcept != null) { + selectCols.add(", cc.visit_source_concept_id"); + groupCols.add(", cc.visit_source_concept_id"); + } else if (entry.getKey().equals("provider_id") && providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", cc.provider_id"); + groupCols.add(", cc.provider_id"); + } else { + selectCols.add(", CAST(null as " + entry.getValue().getDataType().getType() + ") " + entry.getKey()); + } + } + + query = StringUtils.replace(query, "@additionColumnscc", StringUtils.join(selectCols, "")); + query = StringUtils.replace(query, "@additionGroupColumnscc", StringUtils.join(groupCols, "")); + return query; + } + + @Override + public String embedWindowedCriteriaQueryP(String query) { + ArrayList selectColsA = new ArrayList<>(); + + if (visitSourceConcept != null) { + selectColsA.add(", A.visit_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectColsA.add(", A.provider_id"); + } + + query = StringUtils.replace(query, "@p.additionColumns", StringUtils.join(selectColsA, "")); + return query; + } + + @Override + public String embedWrapCriteriaQuery(String query, List selectColsPE, BuilderOptions options) { + ArrayList selectCols = new ArrayList<>(); + + if(!options.isPrimaryCriteria()){ + if (visitSourceConcept != null) { + selectCols.add(", Q.visit_source_concept_id"); + selectColsPE.add(", PE.visit_source_concept_id"); + } + + // providerSpecialty + if (providerSpecialty != null && providerSpecialty.length > 0) { + selectCols.add(", Q.provider_id"); + selectColsPE.add(", PE.provider_id"); + } + } + + query = StringUtils.replace(query, "@QAdditionalColumnsInclusionN", StringUtils.join(selectCols, "")); + return query; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/WindowedCriteria.java b/src/main/java/org/ohdsi/circe/cohortdefinition/WindowedCriteria.java index 39e021b3..5a661658 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/WindowedCriteria.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/WindowedCriteria.java @@ -18,6 +18,10 @@ */ package org.ohdsi.circe.cohortdefinition; +import java.util.Map; + +import org.ohdsi.circe.cohortdefinition.builders.ColumnFieldData; + import com.fasterxml.jackson.annotation.JsonProperty; public class WindowedCriteria { @@ -35,4 +39,7 @@ public class WindowedCriteria { @JsonProperty("IgnoreObservationPeriod") public boolean ignoreObservationPeriod = false; + + // Map contain all distinct field for UNION ALL + public Map mapDistinctField; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/BuilderOptions.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/BuilderOptions.java index 2b0f2a45..40ab770d 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/BuilderOptions.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/BuilderOptions.java @@ -6,5 +6,32 @@ public class BuilderOptions { public List additionalColumns = new ArrayList<>(); + + private boolean useDatetime; + private boolean retainCohortCovariates; + private boolean primaryCriteria = false; + public boolean isUseDatetime() { + return useDatetime; + } + + public boolean isRetainCohortCovariates() { + return retainCohortCovariates; + } + + public void setUseDatetime(Boolean useDatetime) { + this.useDatetime = useDatetime == null ? false: useDatetime; + } + + public void setRetainCohortCovariates(Boolean retainCohortCovariates) { + this.retainCohortCovariates = retainCohortCovariates; + } + + public boolean isPrimaryCriteria() { + return primaryCriteria; + } + + public void setPrimaryCriteria(boolean primaryCriteria) { + this.primaryCriteria = primaryCriteria; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ColumnFieldData.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ColumnFieldData.java new file mode 100644 index 00000000..9b7d4474 --- /dev/null +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ColumnFieldData.java @@ -0,0 +1,29 @@ +package org.ohdsi.circe.cohortdefinition.builders; + +public class ColumnFieldData { + private String name; + + private ColumnFieldDataType dataType; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ColumnFieldDataType getDataType() { + return dataType; + } + + public void setDataType(ColumnFieldDataType dataType) { + this.dataType = dataType; + } + + public ColumnFieldData(String name, ColumnFieldDataType dataType) { + this.name = name; + this.dataType = dataType; + } + +} diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ColumnFieldDataType.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ColumnFieldDataType.java new file mode 100644 index 00000000..09376ef1 --- /dev/null +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ColumnFieldDataType.java @@ -0,0 +1,20 @@ +package org.ohdsi.circe.cohortdefinition.builders; + +public enum ColumnFieldDataType { + INTEGER("int"), NUMERIC("numeric"), VARCHAR("varchar"), DATE("date"); + + private String type; + + ColumnFieldDataType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionEraSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionEraSqlBuilder.java index 4f6183f3..13fbb9a2 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionEraSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionEraSqlBuilder.java @@ -23,7 +23,7 @@ public class ConditionEraSqlBuilder extends CriteriaSqlB // default select columns are the columns that will always be returned from the subquery, but are added to based on the specific criteria private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("ce.person_id", "ce.condition_era_id", "ce.condition_concept_id", "ce.condition_occurrence_count")); - + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -60,7 +60,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first) { @@ -69,11 +69,27 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + if (criteria.occurrenceCount != null) { + cColumns.add("C.condition_occurrence_count"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } + return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); // dateAdjustment or default start/end dates @@ -84,6 +100,11 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("ce.condition_era_start_date as start_date, ce.condition_era_end_date as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("ce.condition_concept_id concept_id"); + } + return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionOccurrenceSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionOccurrenceSqlBuilder.java index 92880b74..a8c6a91a 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionOccurrenceSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionOccurrenceSqlBuilder.java @@ -64,7 +64,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first == true) { @@ -73,12 +73,40 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + // If save covariates is included, add the concept_id column + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + if (criteria.conditionType != null && criteria.conditionType.length > 0) { + cColumns.add("C.condition_type_concept_id"); + } + + if (criteria.conditionSourceConcept != null) { + cColumns.add("C.condition_source_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + cColumns.add("C.provider_id"); + } + + if (criteria.conditionStatus != null && criteria.conditionStatus.length > 0) { + cColumns.add("C.condition_status_concept_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); // Condition Type if (criteria.conditionType != null && criteria.conditionType.length > 0) { @@ -104,6 +132,15 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("co.condition_start_date as start_date, COALESCE(co.condition_end_date, DATEADD(day,1,co.condition_start_date)) as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("co.condition_concept_id concept_id"); + + if (criteria.conditionSourceConcept != null) { + selectCols.add("co.condition_source_concept_id"); + } + } + return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaColumn.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaColumn.java index aa06f369..de8992c8 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaColumn.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaColumn.java @@ -35,7 +35,9 @@ public enum CriteriaColumn { UNIT("unit_concept_id"), VALUE_AS_NUMBER("value_as_number"), VISIT_ID("visit_occurrence_id"), - VISIT_DETAIL_ID("visit_detail_id"); + VISIT_DETAIL_ID("visit_detail_id"), + VALUE_AS_STRING("value_as_string"), + VALUE_AS_CONCEPT_ID("value_as_concept_id"); private final String columnName; diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaSqlBuilder.java index 32dd1051..a2563bf2 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaSqlBuilder.java @@ -20,11 +20,11 @@ public String getCriteriaSql(T criteria, BuilderOptions options) { query = embedCodesetClause(query, criteria); - List selectClauses = resolveSelectClauses(criteria); + List selectClauses = resolveSelectClauses(criteria, options); List joinClauses = resolveJoinClauses(criteria); List whereClauses = resolveWhereClauses(criteria); - query = embedOrdinalExpression(query, criteria, whereClauses); + query = embedOrdinalExpression(query, criteria, whereClauses, options); query = embedSelectClauses(query, selectClauses); query = embedJoinClauses(query, joinClauses); @@ -39,10 +39,10 @@ public String getCriteriaSql(T criteria, BuilderOptions options) { } else { query = StringUtils.replace(query, "@additionalColumns", ""); } + } else { query = StringUtils.replace(query, "@additionalColumns", ""); } - return query; } @@ -80,9 +80,9 @@ protected String embedWhereClauses(String query, List whereClauses) { protected abstract String embedCodesetClause(String query, T criteria); - protected abstract String embedOrdinalExpression(String query, T criteria, List whereClauses); + protected abstract String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options); - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { return new ArrayList(); } @@ -98,4 +98,8 @@ protected List resolveWhereClauses(T criteria) { return whereClauses; } + + protected void addSelectedField(T criteria, BuilderOptions option) { + return; + } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeathSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeathSqlBuilder.java index c79fc122..1e2f2fb2 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeathSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeathSqlBuilder.java @@ -41,7 +41,7 @@ protected String getQueryTemplate() { protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { switch (column) { case DOMAIN_CONCEPT: - return "coalesce(C.cause_concept_id,0)"; + return "coalesce(C.cause_concept_id ,0)"; case DURATION: return "CAST(1 as int)"; default: @@ -61,13 +61,34 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { - + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { + + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + if(!options.isPrimaryCriteria()){ + if (criteria.occurrenceStartDate != null) { + cColumns.add("C.death_date"); + } + + if (criteria.deathType != null && criteria.deathType.length > 0) { + cColumns.add("C.death_type_concept_id"); + } + + if (criteria.deathSourceConcept != null) { + cColumns.add("C.cause_concept_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); // Condition Type if (criteria.deathType != null && criteria.deathType.length > 0) { @@ -80,6 +101,15 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("d.death_date as start_date, DATEADD(day,1,d.death_date) as end_date"); } + + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("d.cause_concept_id concept_id"); + if (criteria.occurrenceStartDate != null) { + selectCols.add("d.death_date"); + } + } + return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeviceExposureSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeviceExposureSqlBuilder.java index 586c15e7..75f65027 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeviceExposureSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeviceExposureSqlBuilder.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Map; import java.util.Set; + import org.ohdsi.circe.cohortdefinition.DateAdjustment; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildDateRangeClause; @@ -26,7 +27,7 @@ public class DeviceExposureSqlBuilder extends Criteria private final Set DEFAULT_COLUMNS = new HashSet<>(Arrays.asList(CriteriaColumn.START_DATE, CriteriaColumn.END_DATE, CriteriaColumn.VISIT_ID)); // default select columns are the columns that will always be returned from the subquery, but are added to based on the specific criteria - private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("de.person_id", "de.device_exposure_id", "de.device_concept_id", + private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("de.person_id", "de.device_exposure_id", "de.device_concept_id", "de.visit_occurrence_id", "de.quantity")); @Override @@ -66,7 +67,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first) { @@ -75,11 +76,42 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + if (criteria.deviceType != null && criteria.deviceType.length > 0) { + cColumns.add("C.device_type_concept_id"); + } + + if (criteria.quantity != null) { + cColumns.add("C.quantity"); + } + + if (criteria.uniqueDeviceId != null) { + cColumns.add("C.unique_device_id"); + } + + if (criteria.deviceSourceConcept != null) { + cColumns.add("C.device_source_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + cColumns.add("C.provider_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); // Device Type if (criteria.deviceType != null && criteria.deviceType.length > 0) { @@ -104,6 +136,15 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("de.device_exposure_start_date as start_date, COALESCE(de.device_exposure_end_date, DATEADD(day,1,de.device_exposure_start_date)) as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("de.device_concept_id concept_id"); + + if (criteria.deviceSourceConcept != null) { + selectCols.add("de.device_source_concept_id"); + } + } + return selectCols; } @@ -177,6 +218,12 @@ protected List resolveWhereClauses(T criteria) { whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType), ","))); } + // unitConceptId + if (criteria.unitConceptId != null && criteria.unitConceptId.length > 0) { + ArrayList conceptIds = getConceptIdsFromConcepts(criteria.unitConceptId); + whereClauses.add(String.format("C.unit_concept_id in (%s)", StringUtils.join(conceptIds, ","))); + } + return whereClauses; } } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DoseEraSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DoseEraSqlBuilder.java index 3f473f86..415d9f6b 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DoseEraSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DoseEraSqlBuilder.java @@ -23,7 +23,7 @@ public class DoseEraSqlBuilder extends CriteriaSqlBuilder private final Set DEFAULT_COLUMNS = new HashSet<>(Arrays.asList(CriteriaColumn.START_DATE, CriteriaColumn.END_DATE, CriteriaColumn.VISIT_ID)); // default select columns are the columns that will always be returned from the subquery, but are added to based on the specific criteria - private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("de.person_id", "de.dose_era_id", "de.drug_concept_id, de.unit_concept_id, de.dose_value")); + private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("de.person_id", "de.dose_era_id", "de.drug_concept_id", "de.unit_concept_id", "de.dose_value")); @Override protected Set getDefaultColumns() { @@ -63,7 +63,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first) { @@ -72,6 +72,32 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + if(!options.isPrimaryCriteria()){ + if (criteria.eraStartDate != null) { + cColumns.add("C.dose_era_start_date"); + } + + if (criteria.eraEndDate != null) { + cColumns.add("C.dose_era_end_date"); + } + + // unit + if (criteria.unit != null && criteria.unit.length > 0) { + cColumns.add("C.unit_concept_id"); + } + + if (criteria.doseValue != null) { + cColumns.add("C.dose_value"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @@ -90,10 +116,15 @@ protected List resolveJoinClauses(T criteria) { } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); - + + // unit + if (criteria.unit != null && criteria.unit.length > 0) { + selectCols.add("de.unit_concept_id"); + } + // dateAdjustment or default start/end dates if (criteria.dateAdjustment != null) { selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, @@ -103,6 +134,10 @@ protected List resolveSelectClauses(T criteria) { selectCols.add("de.dose_era_start_date as start_date, de.dose_era_end_date as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("de.drug_concept_id concept_id"); + } return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugEraSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugEraSqlBuilder.java index acb00829..3c72268a 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugEraSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugEraSqlBuilder.java @@ -23,7 +23,7 @@ public class DrugEraSqlBuilder extends CriteriaSqlBuilder private final Set DEFAULT_COLUMNS = new HashSet<>(Arrays.asList(CriteriaColumn.START_DATE, CriteriaColumn.END_DATE, CriteriaColumn.VISIT_ID)); // default select columns are the columns that will always be returned from the subquery, but are added to based on the specific criteria - private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("de.person_id", "de.drug_era_id", "de.drug_concept_id", + private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("de.person_id", "de.drug_era_id", "de.drug_concept_id", "de.drug_exposure_count", "de.gap_days")); @Override @@ -64,7 +64,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first == true) { @@ -73,11 +73,30 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + if (criteria.occurrenceCount != null) { + cColumns.add("C.drug_exposure_count"); + } + + if (criteria.gapDays != null) { + cColumns.add("C.gap_days"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -91,7 +110,10 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("de.drug_era_start_date as start_date, de.drug_era_end_date as end_date"); } - + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("de.drug_concept_id concept_id"); + } return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugExposureSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugExposureSqlBuilder.java index 7a4a8045..d8905ffc 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugExposureSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugExposureSqlBuilder.java @@ -25,8 +25,8 @@ public class DrugExposureSqlBuilder extends CriteriaSqlB private final Set DEFAULT_COLUMNS = new HashSet<>(Arrays.asList(CriteriaColumn.START_DATE, CriteriaColumn.END_DATE, CriteriaColumn.VISIT_ID)); // default select columns are the columns that will always be returned from the subquery, but are added to based on the specific criteria - private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("de.person_id", "de.drug_exposure_id", "de.drug_concept_id", "de.visit_occurrence_id", - "days_supply", "quantity", "refills")); + private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("de.person_id", "de.drug_exposure_id", "de.drug_concept_id", "de.visit_occurrence_id", + "days_supply", "quantity", "refills")); @Override protected Set getDefaultColumns() { @@ -69,7 +69,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first) { @@ -79,11 +79,59 @@ protected String embedOrdinalExpression(String query, T criteria, List w query = StringUtils.replace(query, "@ordinalExpression", ""); } + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + if (criteria.drugType != null && criteria.drugType.length > 0) { + cColumns.add("C.drug_type_concept_id"); + } + + if (criteria.stopReason != null) { + cColumns.add("C.stop_reason"); + } + + if (criteria.refills != null) { + cColumns.add("C.refills"); + } + + if (criteria.quantity != null) { + cColumns.add("C.quantity"); + } + + if (criteria.daysSupply != null) { + cColumns.add("C.days_supply"); + } + + if (criteria.routeConcept != null && criteria.routeConcept.length > 0) { + cColumns.add("C.route_concept_id"); + } + + if (criteria.lotNumber != null) { + cColumns.add("C.lot_number"); + } + + if (criteria.drugSourceConcept != null) { + cColumns.add("C.drug_source_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + cColumns.add("C.provider_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } + return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -132,6 +180,14 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("de.drug_exposure_start_date as start_date, COALESCE(de.drug_exposure_end_date, DATEADD(day,de.days_supply,de.drug_exposure_start_date), DATEADD(day,1,de.drug_exposure_start_date)) as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("de.drug_concept_id concept_id"); + + if (criteria.drugSourceConcept != null) { + selectCols.add("de.drug_source_concept_id"); + } + } return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/LocationRegionSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/LocationRegionSqlBuilder.java index f7dbd59c..9f7730c4 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/LocationRegionSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/LocationRegionSqlBuilder.java @@ -51,8 +51,11 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { - + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { + if (options != null && options.isRetainCohortCovariates()) { + query = StringUtils.replace(query, "@concept_id", ", C.concept_id"); + } + query = StringUtils.replace(query, "@concept_id", ""); return query; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/MeasurementSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/MeasurementSqlBuilder.java index fe204467..c85607b0 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/MeasurementSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/MeasurementSqlBuilder.java @@ -9,6 +9,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; + import org.ohdsi.circe.cohortdefinition.DateAdjustment; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildDateRangeClause; @@ -25,7 +26,7 @@ public class MeasurementSqlBuilder extends CriteriaSqlBui // default select columns are the columns that will always be returned from the subquery, but are added to based on the specific criteria private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("m.person_id", "m.measurement_id", "m.measurement_concept_id", "m.visit_occurrence_id", - "m.value_as_number", "m.range_high", "m.range_low")); + "m.value_as_number", "m.range_high", "m.range_low")); @Override protected Set getDefaultColumns() { @@ -51,6 +52,11 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { return "C.range_high"; case RANGE_LOW: return "C.range_low"; + case VALUE_AS_CONCEPT_ID: + return "C.value_as_concept_id"; + case UNIT: + return "C.unit_concept_id"; + default: throw new IllegalArgumentException("Invalid CriteriaColumn for Measurement:" + column.toString()); } @@ -60,15 +66,15 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { protected String embedCodesetClause(String query, T criteria) { return StringUtils.replace(query, "@codesetClause", - getCodesetJoinExpression(criteria.codesetId, - "m.measurement_concept_id", - criteria.measurementSourceConcept, - "m.measurement_source_concept_id") + getCodesetJoinExpression(criteria.codesetId, + "m.measurement_concept_id", + criteria.measurementSourceConcept, + "m.measurement_source_concept_id") ); } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first) { @@ -78,12 +84,55 @@ protected String embedOrdinalExpression(String query, T criteria, List w query = StringUtils.replace(query, "@ordinalExpression", ""); } + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + cColumns.add("C.value_as_number"); + if (criteria.valueAsConcept != null && criteria.valueAsConcept.length > 0) { + cColumns.add("C.value_as_concept_id"); + } + // unit + if (criteria.unit != null && criteria.unit.length > 0) { + cColumns.add("C.unit_concept_id"); + } + // range_low + if (criteria.rangeLow != null) { + cColumns.add("C.range_low"); + } + + // range_high + if (criteria.rangeHigh != null) { + cColumns.add("C.range_high"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + cColumns.add("C.provider_id"); + } + + // measurementType + if (criteria.measurementType != null && criteria.measurementType.length > 0) { + cColumns.add("C.measurement_type_concept_id"); + } + + // operator + if (criteria.operator != null && criteria.operator.length > 0) { + cColumns.add("C.operator_concept_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -115,11 +164,15 @@ protected List resolveSelectClauses(T criteria) { // dateAdjustment or default start/end dates if (criteria.dateAdjustment != null) { selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, - criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "m.measurement_date" : "DATEADD(day,1,m.measurement_date)", - criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "m.measurement_date" : "DATEADD(day,1,m.measurement_date)")); + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "m.measurement_date" : "DATEADD(day,1,m.measurement_date)", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "m.measurement_date" : "DATEADD(day,1,m.measurement_date)")); } else { selectCols.add("m.measurement_date as start_date, DATEADD(day,1,m.measurement_date) as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("m.measurement_concept_id concept_id"); + } return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationPeriodSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationPeriodSqlBuilder.java index d403be12..d930cdd9 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationPeriodSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationPeriodSqlBuilder.java @@ -73,13 +73,26 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { - + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + if (criteria.periodType != null && criteria.periodType.length > 0) { + cColumns.add("C.period_type_concept_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -91,6 +104,10 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("op.observation_period_start_date as start_date, op.observation_period_end_date as end_date"); } + + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("op.period_type_concept_id concept_id"); + } return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationSqlBuilder.java index 5206ef23..dc0ae1f5 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationSqlBuilder.java @@ -8,8 +8,9 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; + +import org.ohdsi.circe.cohortdefinition.Criteria; import org.ohdsi.circe.cohortdefinition.DateAdjustment; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildDateRangeClause; @@ -49,6 +50,12 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { return "C.value_as_number"; case DURATION: return "CAST(1 as int)"; + case VALUE_AS_STRING: + return "C.value_as_string"; + case VALUE_AS_CONCEPT_ID: + return "C.value_as_concept_id"; + case UNIT: + return "C.unit_concept_id"; default: throw new IllegalArgumentException("Invalid CriteriaColumn for Observation:" + column.toString()); } @@ -66,7 +73,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first) { @@ -75,12 +82,55 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + cColumns.add("C.value_as_number"); + // measurementType + if (criteria.observationType != null && criteria.observationType.length > 0) { + cColumns.add("C.observation_type_concept_id"); + } + + // valueAsString + if (criteria.valueAsString != null) { + cColumns.add("C.value_as_string"); + } + + // valueAsConcept + if (criteria.valueAsConcept != null && criteria.valueAsConcept.length > 0) { + cColumns.add("C.value_as_concept_id"); + } + + // qualifier + if (criteria.qualifier != null && criteria.qualifier.length > 0) { + cColumns.add("C.qualifier_concept_id"); + } + + // unit + if (criteria.unit != null && criteria.unit.length > 0) { + cColumns.add("C.unit_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + cColumns.add("C.provider_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -108,6 +158,7 @@ protected List resolveSelectClauses(T criteria) { if (criteria.unit != null && criteria.unit.length > 0) { selectCols.add("o.unit_concept_id"); } + // providerSpecialty if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { selectCols.add("o.provider_id"); @@ -121,6 +172,10 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("o.observation_date as start_date, DATEADD(day,1,o.observation_date) as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("o.observation_concept_id concept_id"); + } return selectCols; } @@ -209,4 +264,5 @@ protected List resolveWhereClauses(T criteria) { return whereClauses; } + } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/PayerPlanPeriodSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/PayerPlanPeriodSqlBuilder.java index 6b0b5135..dd33530b 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/PayerPlanPeriodSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/PayerPlanPeriodSqlBuilder.java @@ -70,13 +70,66 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { - + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + if(!options.isPrimaryCriteria()){ + if (criteria.periodStartDate != null) { + cColumns.add("C.payer_plan_period_start_date"); + } + + if (criteria.periodEndDate != null) { + cColumns.add("C.payer_plan_period_end_date"); + } + + if (criteria.payerConcept != null) { + cColumns.add("C.payer_concept_id"); + } + + if (criteria.planConcept != null) { + cColumns.add("C.plan_concept_id"); + } + + if (criteria.sponsorConcept != null) { + cColumns.add("C.sponsor_concept_id"); + } + + if (criteria.stopReasonConcept != null) { + cColumns.add("C.stop_reason_concept_id"); + } + + if (criteria.stopReasonConcept != null) { + cColumns.add("C.stop_reason_concept_id"); + } + + if (criteria.payerSourceConcept != null) { + cColumns.add("C.payer_source_concept_id"); + } + + if (criteria.planSourceConcept != null) { + cColumns.add("C.plan_source_concept_id"); + } + + if (criteria.sponsorSourceConcept != null) { + cColumns.add("C.sponsor_source_concept_id"); + } + + if (criteria.stopReasonSourceConcept != null) { + cColumns.add("C.stop_reason_source_concept_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } + return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -127,6 +180,10 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("ppp.payer_plan_period_start_date as start_date, ppp.payer_plan_period_end_date as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("ppp.payer_concept_id concept_id"); + } return selectCols; } @@ -200,7 +257,7 @@ protected List resolveWhereClauses(T criteria) { // payer concept if (criteria.payerConcept != null) { - whereClauses.add(String.format("C.payer_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.payerConcept)); + whereClauses.add(String.format("C.concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.payerConcept)); } // plan concept diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ProcedureOccurrenceSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ProcedureOccurrenceSqlBuilder.java index b6d30336..833e9069 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ProcedureOccurrenceSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ProcedureOccurrenceSqlBuilder.java @@ -64,7 +64,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first) { @@ -73,11 +73,42 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + if (criteria.procedureType != null && criteria.procedureType.length > 0) { + cColumns.add("C.procedure_type_concept_id"); + } + + if (criteria.modifier != null && criteria.modifier.length > 0) { + cColumns.add("C.modifier_concept_id"); + } + + if (criteria.quantity != null) { + cColumns.add("C.quantity"); + } + + if (criteria.procedureSourceConcept != null) { + cColumns.add("C.procedure_source_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + cColumns.add("C.provider_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -104,6 +135,14 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("po.procedure_date as start_date, DATEADD(day,1,po.procedure_date) as end_date"); } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("po.procedure_concept_id concept_id"); + + if (criteria.procedureSourceConcept != null) { + selectCols.add("po.procedure_source_concept_id"); + } + } return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/SpecimenSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/SpecimenSqlBuilder.java index ee8a802f..abb55351 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/SpecimenSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/SpecimenSqlBuilder.java @@ -1,6 +1,7 @@ package org.ohdsi.circe.cohortdefinition.builders; import org.apache.commons.lang3.StringUtils; +import org.ohdsi.circe.cohortdefinition.DateAdjustment; import org.ohdsi.circe.cohortdefinition.Specimen; import org.ohdsi.circe.helper.ResourceHelper; @@ -40,6 +41,8 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { return "C.specimen_concept_id"; case DURATION: return "CAST(1 as int)"; + case UNIT: + return "C.unit_concept_id"; default: throw new IllegalArgumentException("Invalid CriteriaColumn for Specimen:" + column.toString()); } @@ -56,7 +59,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first) { @@ -65,6 +68,44 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + if(!options.isPrimaryCriteria()){ + if (criteria.occurrenceStartDate != null) { + cColumns.add("C.specimen_date"); + } + + if (criteria.specimenType != null && criteria.specimenType.length > 0) { + cColumns.add("C.specimen_type_concept_id"); + } + + if (criteria.unit != null && criteria.unit.length > 0) { + cColumns.add("C.unit_concept_id"); + } + + if (criteria.quantity != null) { + cColumns.add("C.quantity"); + } + + if (criteria.anatomicSite != null && criteria.anatomicSite.length > 0) { + cColumns.add("C.anatomic_site_concept_id"); + } + + if (criteria.diseaseStatus != null && criteria.diseaseStatus.length > 0) { + cColumns.add("C.disease_status_concept_id"); + } + + if (criteria.sourceId != null) { + cColumns.add("C.specimen_source_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @@ -135,4 +176,59 @@ protected List resolveWhereClauses(T criteria) { return whereClauses; } + + @Override + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { + // as this logic was fully missing comparing to the other SQL builders adding only the ones which belong to the datetime functionality + ArrayList selectCols = new ArrayList<>(); + + selectCols.add("s.person_id"); + selectCols.add("s.specimen_id"); + selectCols.add("s.specimen_date"); + selectCols.add("s.specimen_concept_id"); + + // unit + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("s.specimen_concept_id concept_id"); + } + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "s.specimen_date" : "DATEADD(day,1,s.specimen_date)", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "s.specimen_date" : "DATEADD(day,1,s.specimen_date)")); + } else { + selectCols.add("s.specimen_date as start_date, DATEADD(day,1,s.specimen_date) as end_date"); + } + + if (criteria.quantity != null) { + selectCols.add("s.quantity"); + } + + if (criteria.specimenType != null && criteria.specimenType.length > 0) { + selectCols.add("s.specimen_type_concept_id"); + } + + // unit + if (criteria.unit != null && criteria.unit.length > 0) { + selectCols.add("s.unit_concept_id"); + } + + // anatomicSite + if (criteria.anatomicSite != null && criteria.anatomicSite.length > 0) { + selectCols.add("s.anatomic_site_concept_id"); + } + + // diseaseStatus + if (criteria.diseaseStatus != null && criteria.diseaseStatus.length > 0) { + selectCols.add("s.disease_status_concept_id"); + } + + // sourceId + if (criteria.sourceId != null) { + selectCols.add("s.specimen_source_id"); + } + return selectCols; + } + } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/VisitDetailSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/VisitDetailSqlBuilder.java index 893b7cfd..6fd98091 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/VisitDetailSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/VisitDetailSqlBuilder.java @@ -6,6 +6,7 @@ import org.ohdsi.circe.helper.ResourceHelper; import java.util.*; + import org.ohdsi.circe.cohortdefinition.DateAdjustment; public class VisitDetailSqlBuilder extends CriteriaSqlBuilder { @@ -16,8 +17,8 @@ public class VisitDetailSqlBuilder extends CriteriaSqlBui private final Set DEFAULT_COLUMNS = new HashSet<>(Arrays.asList(CriteriaColumn.START_DATE, CriteriaColumn.END_DATE, CriteriaColumn.VISIT_DETAIL_ID)); // default select columns are the columns that will always be returned from the subquery, but are added to based on the specific criteria - private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("vd.person_id", "vd.visit_detail_id", - "vd.visit_detail_concept_id","vd.visit_occurrence_id")); + private final List DEFAULT_SELECT_COLUMNS = new ArrayList<>(Arrays.asList("vd.person_id", "vd.visit_detail_id", + "vd.visit_detail_concept_id", "vd.visit_occurrence_id")); @Override protected Set getDefaultColumns() { @@ -53,7 +54,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first == true) { whereClauses.add("C.ordinal = 1"); @@ -61,11 +62,40 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + if(!options.isPrimaryCriteria()){ + if (criteria.visitDetailStartDate != null) { + cColumns.add("C.visit_detail_start_date"); + } + + if (criteria.visitDetailEndDate != null) { + cColumns.add("C.visit_detail_end_date"); + } + + if (criteria.visitDetailTypeCS != null) { + cColumns.add("C.visit_detail_type_concept_id"); + } + + if (criteria.visitDetailSourceConcept != null) { + cColumns.add("C.visit_detail_source_concept_id"); + } + + if (criteria.providerSpecialtyCS != null) { + cColumns.add("C.provider_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -90,9 +120,16 @@ protected List resolveSelectClauses(T criteria) { criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "vd.visit_detail_start_date" : "vd.visit_detail_end_date", criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "vd.visit_detail_start_date" : "vd.visit_detail_end_date")); } else { - selectCols.add("vd.visit_detail_start_date as start_date, vd.visit_detail_end_date as end_date"); + selectCols.add("vd.visit_detail_start_date as start_date, vd.visit_detail_end_date as end_date"); + } + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("vd.visit_detail_concept_id concept_id"); + + if (criteria.visitDetailSourceConcept != null) { + selectCols.add("vd.visit_detail_source_concept_id"); + } } - return selectCols; } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/VisitOccurrenceSqlBuilder.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/VisitOccurrenceSqlBuilder.java index 8780f808..0734169a 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/VisitOccurrenceSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/VisitOccurrenceSqlBuilder.java @@ -9,6 +9,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; + import org.ohdsi.circe.cohortdefinition.DateAdjustment; public class VisitOccurrenceSqlBuilder extends CriteriaSqlBuilder { @@ -55,7 +56,7 @@ protected String embedCodesetClause(String query, T criteria) { } @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + protected String embedOrdinalExpression(String query, T criteria, List whereClauses, BuilderOptions options) { // first if (criteria.first != null && criteria.first == true) { whereClauses.add("C.ordinal = 1"); @@ -63,11 +64,31 @@ protected String embedOrdinalExpression(String query, T criteria, List w } else { query = StringUtils.replace(query, "@ordinalExpression", ""); } + + if (options != null && options.isRetainCohortCovariates()) { + List cColumns = new ArrayList<>(); + cColumns.add("C.concept_id"); + + if(!options.isPrimaryCriteria()){ + if (criteria.visitSourceConcept != null) { + cColumns.add("C.visit_source_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + cColumns.add("C.provider_id"); + } + } + + query = StringUtils.replace(query, "@c.additionalColumns", ", " + StringUtils.join(cColumns, ",")); + } else { + query = StringUtils.replace(query, "@c.additionalColumns", ""); + } return query; } @Override - protected List resolveSelectClauses(T criteria) { + protected List resolveSelectClauses(T criteria, BuilderOptions builderOptions) { ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); @@ -94,7 +115,14 @@ protected List resolveSelectClauses(T criteria) { } else { selectCols.add("vo.visit_start_date as start_date, vo.visit_end_date as end_date"); } - + // If save covariates is included, add the concept_id column + if (builderOptions != null && builderOptions.isRetainCohortCovariates()) { + selectCols.add("vo.visit_concept_id concept_id"); + + if (criteria.visitSourceConcept != null) { + selectCols.add("vo.visit_source_concept_id"); + } + } return selectCols; } diff --git a/src/main/resources/resources/cohortdefinition/sql/additionalCriteriaExclude.sql b/src/main/resources/resources/cohortdefinition/sql/additionalCriteriaExclude.sql index 5053a5a9..42489563 100644 --- a/src/main/resources/resources/cohortdefinition/sql/additionalCriteriaExclude.sql +++ b/src/main/resources/resources/cohortdefinition/sql/additionalCriteriaExclude.sql @@ -1,8 +1,8 @@ -- Begin Correlated Criteria -select @indexId as index_id, p.person_id, p.event_id +select @indexId as index_id, p.person_id, p.event_id@additionColumnscc from @eventTable p LEFT JOIN ( @windowedCriteria ) cc on p.person_id = cc.person_id and p.event_id = cc.event_id -GROUP BY p.person_id, p.event_id +GROUP BY p.person_id, p.event_id@additionGroupColumnscc @occurrenceCriteria --- End Correlated Criteria +-- End Correlated Criteria \ No newline at end of file diff --git a/src/main/resources/resources/cohortdefinition/sql/additionalCriteriaInclude.sql b/src/main/resources/resources/cohortdefinition/sql/additionalCriteriaInclude.sql index c9ca1366..1353dfeb 100644 --- a/src/main/resources/resources/cohortdefinition/sql/additionalCriteriaInclude.sql +++ b/src/main/resources/resources/cohortdefinition/sql/additionalCriteriaInclude.sql @@ -1,6 +1,6 @@ -- Begin Correlated Criteria -select @indexId as index_id, cc.person_id, cc.event_id +select @indexId as index_id, cc.person_id, cc.event_id@additionColumnscc from (@windowedCriteria ) cc -GROUP BY cc.person_id, cc.event_id +GROUP BY cc.person_id, cc.event_id@additionGroupColumnscc @occurrenceCriteria --- End Correlated Criteria +-- End Correlated Criteria \ No newline at end of file diff --git a/src/main/resources/resources/cohortdefinition/sql/cohortInclusionAnalysis.sql b/src/main/resources/resources/cohortdefinition/sql/cohortInclusionAnalysis.sql index 8ce52def..fb20247d 100644 --- a/src/main/resources/resources/cohortdefinition/sql/cohortInclusionAnalysis.sql +++ b/src/main/resources/resources/cohortdefinition/sql/cohortInclusionAnalysis.sql @@ -39,5 +39,5 @@ FROM from @results_database_schema.cohort_inclusion_result sr CROSS JOIN (select count(*) as total_rules from #inclusion_rules) RuleTotal where sr.mode_id = @inclusionImpactMode and sr.@cohort_id_field_name = @target_cohort_id and sr.inclusion_rule_mask = POWER(cast(2 as bigint),RuleTotal.total_rules)-1 -) FC + ) FC ; diff --git a/src/main/resources/resources/cohortdefinition/sql/conditionEra.sql b/src/main/resources/resources/cohortdefinition/sql/conditionEra.sql index 15246416..53fc6386 100644 --- a/src/main/resources/resources/cohortdefinition/sql/conditionEra.sql +++ b/src/main/resources/resources/cohortdefinition/sql/conditionEra.sql @@ -1,6 +1,6 @@ -- Begin Condition Era Criteria select C.person_id, C.condition_era_id as event_id, C.start_date, C.end_date, - CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/conditionOccurrence.sql b/src/main/resources/resources/cohortdefinition/sql/conditionOccurrence.sql index 2c423923..486f5a3c 100644 --- a/src/main/resources/resources/cohortdefinition/sql/conditionOccurrence.sql +++ b/src/main/resources/resources/cohortdefinition/sql/conditionOccurrence.sql @@ -1,6 +1,6 @@ -- Begin Condition Occurrence Criteria SELECT C.person_id, C.condition_occurrence_id as event_id, C.start_date, C.end_date, - C.visit_occurrence_id, C.start_date as sort_date@additionalColumns + C.visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns FROM ( SELECT @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/customEraStrategy.sql b/src/main/resources/resources/cohortdefinition/sql/customEraStrategy.sql index ddb4e6a8..4e6b0bc4 100644 --- a/src/main/resources/resources/cohortdefinition/sql/customEraStrategy.sql +++ b/src/main/resources/resources/cohortdefinition/sql/customEraStrategy.sql @@ -21,7 +21,7 @@ FROM ( ) E ; -select et.event_id, et.person_id, ERAS.era_end_date as end_date +select et.event_id, et.person_id, ERAS.era_end_date as end_date@concept_id INTO #strategy_ends from @eventTable et JOIN diff --git a/src/main/resources/resources/cohortdefinition/sql/dateOffsetStrategy.sql b/src/main/resources/resources/cohortdefinition/sql/dateOffsetStrategy.sql index 16a7e395..692bafd5 100644 --- a/src/main/resources/resources/cohortdefinition/sql/dateOffsetStrategy.sql +++ b/src/main/resources/resources/cohortdefinition/sql/dateOffsetStrategy.sql @@ -1,6 +1,6 @@ -- date offset strategy -select event_id, person_id, - case when DATEADD(day,@offset,@dateField) > op_end_date then op_end_date else DATEADD(day,@offset,@dateField) end as end_date +select event_id, person_id, + case when DATEADD(day,@offset,@dateField) > op_end_date then op_end_date else DATEADD(day,@offset,@dateField) end as end_date @concept_id INTO #strategy_ends from @eventTable; diff --git a/src/main/resources/resources/cohortdefinition/sql/death.sql b/src/main/resources/resources/cohortdefinition/sql/death.sql index e97267aa..acfc93f1 100644 --- a/src/main/resources/resources/cohortdefinition/sql/death.sql +++ b/src/main/resources/resources/cohortdefinition/sql/death.sql @@ -1,6 +1,6 @@ -- Begin Death Criteria select C.person_id, C.person_id as event_id, C.start_date, c.end_date, - CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause diff --git a/src/main/resources/resources/cohortdefinition/sql/deviceExposure.sql b/src/main/resources/resources/cohortdefinition/sql/deviceExposure.sql index d92a520c..b2fc65ef 100644 --- a/src/main/resources/resources/cohortdefinition/sql/deviceExposure.sql +++ b/src/main/resources/resources/cohortdefinition/sql/deviceExposure.sql @@ -1,6 +1,6 @@ -- Begin Device Exposure Criteria select C.person_id, C.device_exposure_id as event_id, C.start_date, C.end_date, - C.visit_occurrence_id, C.start_date as sort_date@additionalColumns + C.visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/doseEra.sql b/src/main/resources/resources/cohortdefinition/sql/doseEra.sql index 30e54b91..52b10d74 100644 --- a/src/main/resources/resources/cohortdefinition/sql/doseEra.sql +++ b/src/main/resources/resources/cohortdefinition/sql/doseEra.sql @@ -1,6 +1,6 @@ -- Begin Dose Era Criteria select C.person_id, C.dose_era_id as event_id, C.start_date, C.end_date, - CAST(NULL as bigint) as visit_occurrence_id,C.start_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id,C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/drugEra.sql b/src/main/resources/resources/cohortdefinition/sql/drugEra.sql index 0e163dad..f6060be7 100644 --- a/src/main/resources/resources/cohortdefinition/sql/drugEra.sql +++ b/src/main/resources/resources/cohortdefinition/sql/drugEra.sql @@ -1,6 +1,6 @@ -- Begin Drug Era Criteria select C.person_id, C.drug_era_id as event_id, C.start_date, C.end_date, - CAST(NULL as bigint) as visit_occurrence_id,C.start_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id,C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/drugExposure.sql b/src/main/resources/resources/cohortdefinition/sql/drugExposure.sql index 930eec6c..3b3f2f68 100644 --- a/src/main/resources/resources/cohortdefinition/sql/drugExposure.sql +++ b/src/main/resources/resources/cohortdefinition/sql/drugExposure.sql @@ -1,6 +1,6 @@ -- Begin Drug Exposure Criteria select C.person_id, C.drug_exposure_id as event_id, C.start_date, C.end_date, - C.visit_occurrence_id,C.start_date as sort_date@additionalColumns + C.visit_occurrence_id,C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/eventTableExpression.sql b/src/main/resources/resources/cohortdefinition/sql/eventTableExpression.sql index 2a0ce739..9171417e 100644 --- a/src/main/resources/resources/cohortdefinition/sql/eventTableExpression.sql +++ b/src/main/resources/resources/cohortdefinition/sql/eventTableExpression.sql @@ -1,4 +1,4 @@ -SELECT Q.person_id, Q.event_id, Q.start_date, Q.end_date, Q.visit_occurrence_id, OP.observation_period_start_date as op_start_date, OP.observation_period_end_date as op_end_date +SELECT Q.person_id, Q.event_id, Q.start_date, Q.end_date, Q.visit_occurrence_id, OP.observation_period_start_date as op_start_date, OP.observation_period_end_date as op_end_date@concept_id @QAdditionalColumnsInclusionN FROM (@eventQuery) Q JOIN @cdm_database_schema.OBSERVATION_PERIOD OP on Q.person_id = OP.person_id and OP.observation_period_start_date <= Q.start_date and OP.observation_period_end_date >= Q.start_date diff --git a/src/main/resources/resources/cohortdefinition/sql/generateCohort.sql b/src/main/resources/resources/cohortdefinition/sql/generateCohort.sql index c571d56a..df70956a 100644 --- a/src/main/resources/resources/cohortdefinition/sql/generateCohort.sql +++ b/src/main/resources/resources/cohortdefinition/sql/generateCohort.sql @@ -1,10 +1,12 @@ @codesetQuery -SELECT event_id, person_id, start_date, end_date, op_start_date, op_end_date, visit_occurrence_id +-- concept_id: temp identify of #qualified_events. Created to join the qualified_events, inclusion_events, strategy_ends tables + +SELECT event_id, person_id, start_date, end_date, op_start_date, op_end_date, visit_occurrence_id@concept_id INTO #qualified_events -FROM +FROM ( - select pe.event_id, pe.person_id, pe.start_date, pe.end_date, pe.op_start_date, pe.op_end_date, row_number() over (partition by pe.person_id order by pe.start_date @QualifiedEventSort) as ordinal, cast(pe.visit_occurrence_id as bigint) as visit_occurrence_id + select pe.event_id, pe.person_id, pe.start_date, pe.end_date, pe.op_start_date, pe.op_end_date@pe_concept_id, row_number() over (partition by pe.person_id order by pe.start_date @QualifiedEventSort) as ordinal, cast(pe.visit_occurrence_id as bigint) as visit_occurrence_id FROM (@primaryEventsQuery) pe @additionalCriteriaQuery ) QE @@ -15,16 +17,16 @@ FROM @inclusionCohortInserts -select event_id, person_id, start_date, end_date, op_start_date, op_end_date +select event_id, person_id, start_date, end_date, op_start_date, op_end_date@concept_id @allInclusionColumnsInserts into #included_events FROM ( - SELECT event_id, person_id, start_date, end_date, op_start_date, op_end_date, row_number() over (partition by person_id order by start_date @IncludedEventSort) as ordinal + SELECT event_id, person_id, start_date, end_date, op_start_date, op_end_date, row_number() over (partition by person_id order by start_date @IncludedEventSort) as ordinal@concept_id@allInclusionColumnsInserts from ( - select Q.event_id, Q.person_id, Q.start_date, Q.end_date, Q.op_start_date, Q.op_end_date, SUM(coalesce(POWER(cast(2 as bigint), I.inclusion_rule_id), 0)) as inclusion_rule_mask + select Q.event_id, Q.person_id, Q.start_date, Q.end_date, Q.op_start_date, Q.op_end_date, SUM(coalesce(POWER(cast(2 as bigint), I.inclusion_rule_id), 0)) as inclusion_rule_mask @Qconcept_id@allInclusionColumnsInserts from #qualified_events Q LEFT JOIN #inclusion_events I on I.person_id = Q.person_id and I.event_id = Q.event_id - GROUP BY Q.event_id, Q.person_id, Q.start_date, Q.end_date, Q.op_start_date, Q.op_end_date + GROUP BY Q.event_id, Q.person_id, Q.start_date, Q.end_date, Q.op_start_date, Q.op_end_date @Qconcept_id@allInclusionColumnsInserts ) MG -- matching groups {@ruleTotal != 0}?{ -- the matching group with all bits set ( POWER(2,# of inclusion rules) - 1 = inclusion_rule_mask @@ -37,12 +39,12 @@ FROM ( @strategy_ends_temp_tables -- generate cohort periods into #final_cohort -select person_id, start_date, end_date +select person_id, start_date, end_date INTO #cohort_rows from ( -- first_ends - select F.person_id, F.start_date, F.end_date + select F.person_id, F.start_date, F.end_date FROM ( - select I.event_id, I.person_id, I.start_date, CE.end_date, row_number() over (partition by I.person_id, I.event_id order by CE.end_date) as ordinal + select I.event_id, I.person_id, I.start_date, CE.end_date, row_number() over (partition by I.person_id, I.event_id order by CE.end_date) as ordinal from #included_events I join ( -- cohort_ends -- cohort exit dates @@ -52,8 +54,7 @@ from ( -- first_ends WHERE F.ordinal = 1 ) FE; - -select person_id, min(start_date) as start_date, DATEADD(day,-1 * @eraconstructorpad, max(end_date)) as end_date +select person_id, min(start_date) as start_date, DATEADD(day,-1 * @eraconstructorpad, max(end_date)) as end_date into #final_cohort from ( select person_id, start_date, end_date, sum(is_start) over (partition by person_id order by start_date, is_start desc rows unbounded preceding) group_idx @@ -84,20 +85,20 @@ delete from @results_database_schema.cohort_censor_stats where @cohort_id_field_ @inclusionRuleTable --- Find the event that is the 'best match' per person. +-- Find the event that is the 'best match' per person. -- the 'best match' is defined as the event that satisfies the most inclusion rules. -- ties are solved by choosing the event that matches the earliest inclusion rule, and then earliest. -select q.person_id, q.event_id +select q.person_id, q.event_id into #best_events from #qualified_events Q join ( - SELECT R.person_id, R.event_id, ROW_NUMBER() OVER (PARTITION BY R.person_id ORDER BY R.rule_count DESC,R.min_rule_id ASC, R.start_date ASC) AS rank_value + SELECT R.person_id, R.event_id, ROW_NUMBER() OVER (PARTITION BY R.person_id ORDER BY R.rule_count DESC,R.min_rule_id ASC, R.start_date ASC) AS rank_value FROM ( - SELECT Q.person_id, Q.event_id, COALESCE(COUNT(DISTINCT I.inclusion_rule_id), 0) AS rule_count, COALESCE(MIN(I.inclusion_rule_id), 0) AS min_rule_id, Q.start_date + SELECT Q.person_id, Q.event_id, COALESCE(COUNT(DISTINCT I.inclusion_rule_id), 0) AS rule_count, COALESCE(MIN(I.inclusion_rule_id), 0) AS min_rule_id, Q.start_date FROM #qualified_events Q LEFT JOIN #inclusion_events I ON q.person_id = i.person_id AND q.event_id = i.event_id - GROUP BY Q.person_id, Q.event_id, Q.start_date + GROUP BY Q.person_id, Q.event_id, Q.start_date ) R ) ranked on Q.person_id = ranked.person_id and Q.event_id = ranked.event_id WHERE ranked.rank_value = 1 @@ -116,6 +117,30 @@ WHERE ranked.rank_value = 1 @inclusionImpactAnalysisByPersonQuery -- END: Inclusion Impact Analysis - person +-- If retain_cohort_covariates is checked, it is processed to create the #final_cohort_details table +{@retain_cohort_covariates == 1}?{ +-- BEGIN: Retain Cohort Covariates +select qe.op_start_date, qe.op_end_date, qe.visit_occurrence_id, + ie.* + @strategy_ends_columns +into #final_cohort_details +from #qualified_events qe +left join #inclusion_events ie on qe.person_id = ie.person_id AND qe.event_id = ie.event_id +@leftjoinEraStrategy +; + +-- If @results_database_schema."cohort_details_@result_cohort_id" exists, remove it and create new one. +DROP TABLE IF EXISTS @results_database_schema."cohort_details_@result_cohort_id"; + +select fc.* +into @results_database_schema."cohort_details_@result_cohort_id" +from #final_cohort_details fc +; +-- END: Retain Cohort Covariates +TRUNCATE TABLE #final_cohort_details; +DROP TABLE #final_cohort_details; +} + TRUNCATE TABLE #best_events; DROP TABLE #best_events; @@ -124,7 +149,6 @@ DROP TABLE #inclusion_rules; } @strategy_ends_cleanup - TRUNCATE TABLE #cohort_rows; DROP TABLE #cohort_rows; @@ -141,4 +165,4 @@ TRUNCATE TABLE #included_events; DROP TABLE #included_events; TRUNCATE TABLE #Codesets; -DROP TABLE #Codesets; +DROP TABLE #Codesets; \ No newline at end of file diff --git a/src/main/resources/resources/cohortdefinition/sql/groupQuery.sql b/src/main/resources/resources/cohortdefinition/sql/groupQuery.sql index 01252e94..7c3007a9 100644 --- a/src/main/resources/resources/cohortdefinition/sql/groupQuery.sql +++ b/src/main/resources/resources/cohortdefinition/sql/groupQuery.sql @@ -1,14 +1,14 @@ -- Begin Criteria Group -select @indexId as index_id, person_id, event_id +select @indexId as index_id, person_id, event_id @additonColumnsGroup FROM ( - select E.person_id, E.event_id + select E.person_id, E.event_id@e.additonColumns FROM @eventTable E @joinType JOIN ( @criteriaQueries ) CQ on E.person_id = CQ.person_id and E.event_id = CQ.event_id - GROUP BY E.person_id, E.event_id + GROUP BY E.person_id, E.event_id@e.additonColumns @occurrenceCountClause ) G -- End Criteria Group diff --git a/src/main/resources/resources/cohortdefinition/sql/inclusionrule.sql b/src/main/resources/resources/cohortdefinition/sql/inclusionrule.sql index bee0cb9b..15b49694 100644 --- a/src/main/resources/resources/cohortdefinition/sql/inclusionrule.sql +++ b/src/main/resources/resources/cohortdefinition/sql/inclusionrule.sql @@ -1,9 +1,11 @@ -select @inclusion_rule_id as inclusion_rule_id, person_id, event_id +select @inclusion_rule_id as inclusion_rule_id, person_id, + event_id, + start_date, end_date @concept_id @additionalColumnsInclusionN INTO #Inclusion_@inclusion_rule_id -FROM -( - select pe.person_id, pe.event_id - FROM #qualified_events pe - @additionalCriteriaQuery -) Results -; +FROM + ( + select pe.person_id, pe.event_id, pe.start_date, pe.end_date @conceptid @additionalColumnsCriteriaQuery + FROM #qualified_events pe + @additionalCriteriaQuery + ) Results +; \ No newline at end of file diff --git a/src/main/resources/resources/cohortdefinition/sql/locationRegion.sql b/src/main/resources/resources/cohortdefinition/sql/locationRegion.sql index 27c621df..4217f3b0 100644 --- a/src/main/resources/resources/cohortdefinition/sql/locationRegion.sql +++ b/src/main/resources/resources/cohortdefinition/sql/locationRegion.sql @@ -5,7 +5,7 @@ select C.start_date as start_date, ISNULL(C.end_date, DATEFROMPARTS(2099,12,31)) as end_date, CAST(NULL as bigint) as visit_occurrence_id, - C.start_date as sort_date@additionalColumns + C.start_date as sort_date@additionalColumns @concept_id from ( select l.*, lh.* diff --git a/src/main/resources/resources/cohortdefinition/sql/measurement.sql b/src/main/resources/resources/cohortdefinition/sql/measurement.sql index f3064700..c6a547b7 100644 --- a/src/main/resources/resources/cohortdefinition/sql/measurement.sql +++ b/src/main/resources/resources/cohortdefinition/sql/measurement.sql @@ -1,6 +1,6 @@ -- Begin Measurement Criteria select C.person_id, C.measurement_id as event_id, C.start_date, C.end_date, - C.visit_occurrence_id, C.start_date as sort_date@additionalColumns + C.visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/observation.sql b/src/main/resources/resources/cohortdefinition/sql/observation.sql index a3381072..cb35dbc7 100644 --- a/src/main/resources/resources/cohortdefinition/sql/observation.sql +++ b/src/main/resources/resources/cohortdefinition/sql/observation.sql @@ -1,6 +1,6 @@ -- Begin Observation Criteria select C.person_id, C.observation_id as event_id, C.start_date, C.END_DATE, - C.visit_occurrence_id, C.start_date as sort_date@additionalColumns + C.visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/observationPeriod.sql b/src/main/resources/resources/cohortdefinition/sql/observationPeriod.sql index e93c8d84..6ab8a093 100644 --- a/src/main/resources/resources/cohortdefinition/sql/observationPeriod.sql +++ b/src/main/resources/resources/cohortdefinition/sql/observationPeriod.sql @@ -1,6 +1,6 @@ -- Begin Observation Period Criteria select C.person_id, C.observation_period_id as event_id, @startDateExpression as start_date, @endDateExpression as end_date, - CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( diff --git a/src/main/resources/resources/cohortdefinition/sql/payerPlanPeriod.sql b/src/main/resources/resources/cohortdefinition/sql/payerPlanPeriod.sql index ce96290b..f73098d4 100644 --- a/src/main/resources/resources/cohortdefinition/sql/payerPlanPeriod.sql +++ b/src/main/resources/resources/cohortdefinition/sql/payerPlanPeriod.sql @@ -1,6 +1,6 @@ -- Begin Payer Plan Period Criteria select C.person_id, C.payer_plan_period_id as event_id, @startDateExpression as start_date, @endDateExpression as end_date, - CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( diff --git a/src/main/resources/resources/cohortdefinition/sql/primaryEventsQuery.sql b/src/main/resources/resources/cohortdefinition/sql/primaryEventsQuery.sql index 7f878ac7..a93a3f45 100644 --- a/src/main/resources/resources/cohortdefinition/sql/primaryEventsQuery.sql +++ b/src/main/resources/resources/cohortdefinition/sql/primaryEventsQuery.sql @@ -1,10 +1,10 @@ -- Begin Primary Events -select P.ordinal as event_id, P.person_id, P.start_date, P.end_date, op_start_date, op_end_date, cast(P.visit_occurrence_id as bigint) as visit_occurrence_id +select P.ordinal as event_id, P.person_id, P.start_date, P.end_date, op_start_date, op_end_date, cast(P.visit_occurrence_id as bigint) as visit_occurrence_id @concept_id FROM ( select E.person_id, E.start_date, E.end_date, row_number() OVER (PARTITION BY E.person_id ORDER BY E.sort_date @EventSort, E.event_id) ordinal, - OP.observation_period_start_date as op_start_date, OP.observation_period_end_date as op_end_date, cast(E.visit_occurrence_id as bigint) as visit_occurrence_id + OP.observation_period_start_date as op_start_date, OP.observation_period_end_date as op_end_date, cast(E.visit_occurrence_id as bigint) as visit_occurrence_id @concept_id FROM ( @criteriaQueries diff --git a/src/main/resources/resources/cohortdefinition/sql/procedureOccurrence.sql b/src/main/resources/resources/cohortdefinition/sql/procedureOccurrence.sql index aeb4f79e..d0e54d7e 100644 --- a/src/main/resources/resources/cohortdefinition/sql/procedureOccurrence.sql +++ b/src/main/resources/resources/cohortdefinition/sql/procedureOccurrence.sql @@ -1,6 +1,6 @@ -- Begin Procedure Occurrence Criteria select C.person_id, C.procedure_occurrence_id as event_id, C.start_date, C.end_date, - C.visit_occurrence_id, C.start_date as sort_date@additionalColumns + C.visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/specimen.sql b/src/main/resources/resources/cohortdefinition/sql/specimen.sql index 98eeccea..82a0664b 100644 --- a/src/main/resources/resources/cohortdefinition/sql/specimen.sql +++ b/src/main/resources/resources/cohortdefinition/sql/specimen.sql @@ -1,9 +1,9 @@ -- Begin Specimen Criteria select C.person_id, C.specimen_id as event_id, C.specimen_date as start_date, DATEADD(d,1,C.specimen_date) as end_date, - CAST(NULL as bigint) as visit_occurrence_id, C.specimen_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id, C.specimen_date as sort_date@additionalColumns @c.additionalColumns from ( - select s.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.SPECIMEN s @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/visitDetail.sql b/src/main/resources/resources/cohortdefinition/sql/visitDetail.sql index 569c1beb..b0dc4e26 100644 --- a/src/main/resources/resources/cohortdefinition/sql/visitDetail.sql +++ b/src/main/resources/resources/cohortdefinition/sql/visitDetail.sql @@ -1,6 +1,6 @@ -- Begin Visit Detail Criteria select C.person_id, C.visit_detail_id as event_id, C.start_date, C.end_date, - C.visit_occurrence_id, C.start_date as sort_date@additionalColumns + C.visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/visitOccurrence.sql b/src/main/resources/resources/cohortdefinition/sql/visitOccurrence.sql index 56c6d0f4..b45b0962 100644 --- a/src/main/resources/resources/cohortdefinition/sql/visitOccurrence.sql +++ b/src/main/resources/resources/cohortdefinition/sql/visitOccurrence.sql @@ -1,6 +1,6 @@ -- Begin Visit Occurrence Criteria select C.person_id, C.visit_occurrence_id as event_id, C.start_date, C.end_date, - C.visit_occurrence_id, C.start_date as sort_date@additionalColumns + C.visit_occurrence_id, C.start_date as sort_date@additionalColumns @c.additionalColumns from ( select @selectClause @ordinalExpression diff --git a/src/main/resources/resources/cohortdefinition/sql/windowedCriteria.sql b/src/main/resources/resources/cohortdefinition/sql/windowedCriteria.sql index 1ccc9203..3e87f470 100644 --- a/src/main/resources/resources/cohortdefinition/sql/windowedCriteria.sql +++ b/src/main/resources/resources/cohortdefinition/sql/windowedCriteria.sql @@ -1,4 +1,4 @@ -SELECT p.person_id, p.event_id @additionalColumns +SELECT p.person_id, p.event_id @additionalColumns @p.additionColumns FROM @eventTable P JOIN ( @criteriaQuery diff --git a/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_0_0_Test.java b/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_0_0_Test.java index 06d8652a..e8f17e6f 100644 --- a/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_0_0_Test.java +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_0_0_Test.java @@ -7,7 +7,6 @@ import java.lang.reflect.Field; import java.sql.SQLException; import com.github.mjeanroy.dbunit.core.dataset.DataSetFactory; -import org.apache.commons.lang3.StringUtils; import org.dbunit.Assertion; import org.dbunit.DatabaseUnitException; import org.dbunit.database.IDatabaseConnection; @@ -45,6 +44,7 @@ private static CohortExpressionQueryBuilder.BuildExpressionQueryOptions buildExp options.generateStats = true; options.resultSchema = resultsSchema; options.targetTable = resultsSchema + ".cohort"; + options.retainCohortCovariates = false; return options; } @@ -100,6 +100,7 @@ public void loadTestData() throws SQLException, DataSetException { public void rawJsonTest() throws SQLException { final CohortExpressionQueryBuilder.BuildExpressionQueryOptions options = buildExpressionQueryOptions(1,"allCriteriaTest"); + options.retainCohortCovariates = true; // prepare results schema prepareSchema(options.resultSchema, RESULTS_DDL_PATH); @@ -115,7 +116,6 @@ public void rawJsonTest() throws SQLException { // execute on database, expect no errors jdbcTemplate.batchUpdate(SqlSplit.splitSql(cohortSql)); } - /* Cohort Expression Tests */ @Test @@ -137,6 +137,26 @@ public void allCriteriaTest() throws SQLException { jdbcTemplate.batchUpdate(SqlSplit.splitSql(cohortSql)); } + @Test + public void allCriteriaTestWithRetainingCohortCovariates() throws SQLException { + + final CohortExpressionQueryBuilder.BuildExpressionQueryOptions options = buildExpressionQueryOptions(1,"allCriteriaTest"); + options.retainCohortCovariates = true; + + // prepare results schema + prepareSchema(options.resultSchema, RESULTS_DDL_PATH); + + // load 'all' criteria json + final CohortExpression expression = CohortExpression + .fromJson(ResourceHelper.GetResourceAsString("/cohortgeneration/allCriteria/allCriteriaExpression.json")); + + // build Sql + final String cohortSql = buildExpressionSql(expression, options); + + // execute on database, expect no errors + jdbcTemplate.batchUpdate(SqlSplit.splitSql(cohortSql)); + } + /* first occurrence tests */ private void setFirstOccurrenceCriteria(final Criteria c) throws Exception { final Field first = c.getClass().getDeclaredField("first"); @@ -329,7 +349,6 @@ public void testGroups() throws Exception { // execute on database, expect no errors jdbcTemplate.batchUpdate(SqlSplit.splitSql(cohortSql)); - // cohort 4: outer group 'ALL', change inner group to 'at most 0' // No one passes, since that arrangement is a contradiction expression.additionalCriteria.type = "ALL"; @@ -357,7 +376,7 @@ public void testGroups() throws Exception { final ITable expectedTable = expectedDataSet.getTable(RESULTS_SCHEMA + ".cohort"); // Assert actual database table match expected table - Assertion.assertEquals(expectedTable, actualTable); + Assertion.assertEquals(expectedTable, actualTable); } diff --git a/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_2_0_Test.java b/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_2_0_Test.java index b06604a1..d10b1e34 100644 --- a/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_2_0_Test.java +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_2_0_Test.java @@ -52,6 +52,7 @@ private static CohortExpressionQueryBuilder.BuildExpressionQueryOptions buildExp options.generateStats = true; options.resultSchema = resultsSchema; options.targetTable = resultsSchema + ".cohort"; + options.retainCohortCovariates = false; return options; } diff --git a/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_3_0_Test.java b/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_3_0_Test.java new file mode 100644 index 00000000..eccc82e5 --- /dev/null +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/CohortGeneration_5_3_0_Test.java @@ -0,0 +1,111 @@ +package org.ohdsi.circe.cohortdefinition; + +import java.sql.SQLException; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.ohdsi.circe.AbstractDatabaseTest; +import org.ohdsi.circe.helper.ResourceHelper; +import org.ohdsi.sql.SqlRender; +import org.ohdsi.sql.SqlSplit; +import org.ohdsi.sql.SqlTranslate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +public class CohortGeneration_5_3_0_Test extends AbstractDatabaseTest { + private final static Logger log = LoggerFactory.getLogger(CohortGeneration_5_3_0_Test.class); + private static final String CDM_DDL_PATH = "/ddl/cdm_v5.3.sql"; + private static final String RESULTS_DDL_PATH = "/ddl/resultsSchema.sql"; + + private static CohortExpressionQueryBuilder.BuildExpressionQueryOptions buildExpressionQueryOptions( + final int cohortId, final String resultsSchema) { + final CohortExpressionQueryBuilder.BuildExpressionQueryOptions options = new CohortExpressionQueryBuilder.BuildExpressionQueryOptions(); + options.cdmSchema = "cdm"; + options.cohortId = cohortId; + options.generateStats = true; + options.resultSchema = resultsSchema; + options.targetTable = resultsSchema + ".cohort"; + + return options; + } + + private static String buildExpressionSql(final CohortExpression expression, + final CohortExpressionQueryBuilder.BuildExpressionQueryOptions options) { + // build SQL + final CohortExpressionQueryBuilder builder = new CohortExpressionQueryBuilder(); + String cohortSql = builder.buildExpressionQuery(expression, options); + + // translate to PG + cohortSql = SqlRender.renderSql(SqlTranslate.translateSql(cohortSql, "postgresql"), null, null); + + return cohortSql; + } + + @BeforeClass + public static void beforeClass() { + jdbcTemplate = new JdbcTemplate(getDataSource()); + prepareSchema("cdm", CDM_DDL_PATH); + } + + @Test + public void allCriteriaTest() throws SQLException { + + final CohortExpressionQueryBuilder.BuildExpressionQueryOptions options = buildExpressionQueryOptions(1, + "allCriteriaTest"); + + // prepare results schema + prepareSchema(options.resultSchema, RESULTS_DDL_PATH); + + // load 'all' criteria json + final CohortExpression expression = CohortExpression.fromJson( + ResourceHelper.GetResourceAsString("/cohortgeneration/allCriteria/criteriaWithDateTime.json")); + + // build Sql + final String cohortSql = buildExpressionSql(expression, options); + + // execute on database, expect no errors + jdbcTemplate.batchUpdate(SqlSplit.splitSql(cohortSql)); + } + + @Test + public void allCriteriaTestWithRetainingCohortCovariates() throws SQLException { + + final CohortExpressionQueryBuilder.BuildExpressionQueryOptions options = buildExpressionQueryOptions(1, + "allCriteriaTest"); + options.retainCohortCovariates = true; + + // prepare results schema + prepareSchema(options.resultSchema, RESULTS_DDL_PATH); + + // load 'all' criteria json + final CohortExpression expression = CohortExpression.fromJson( + ResourceHelper.GetResourceAsString("/cohortgeneration/allCriteria/criteriaWithDateTime.json")); + + // build Sql + final String cohortSql = buildExpressionSql(expression, options); + + // execute on database, expect no errors + jdbcTemplate.batchUpdate(SqlSplit.splitSql(cohortSql)); + } + + @Test + public void allCriteriaTestWithTimeUnitInterval() throws SQLException { + + final CohortExpressionQueryBuilder.BuildExpressionQueryOptions options = buildExpressionQueryOptions(1, + "allCriteriaTest"); + + // prepare results schema + prepareSchema(options.resultSchema, RESULTS_DDL_PATH); + + // load 'all' criteria json + final CohortExpression expression = CohortExpression.fromJson(ResourceHelper + .GetResourceAsString("/cohortgeneration/allCriteria/criteriaWithDateTime.json")); + + // build Sql + final String cohortSql = buildExpressionSql(expression, options); + + // execute on database, expect no errors + jdbcTemplate.batchUpdate(SqlSplit.splitSql(cohortSql)); + } +} diff --git a/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CorelatedCriteria_5_3_0_Test.java b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CorelatedCriteria_5_3_0_Test.java index c762aaa6..494edf67 100644 --- a/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CorelatedCriteria_5_3_0_Test.java +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CorelatedCriteria_5_3_0_Test.java @@ -88,7 +88,7 @@ public void visitDetailCodesetCriteriaTest() throws Exception { visitDetail.genderCS = inCsSelection; // translate to PG - String inGenderQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable); + String inGenderQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable, false); inGenderQuery = inGenderQuery.replace("#Codesets", RESULTS_SCHEMA + ".codesets"); String translatedInGenderQuery = SqlRender.renderSql(SqlTranslate.translateSql(inGenderQuery, "postgresql"), new String[] {"cdm_database_schema", "indexId"}, @@ -104,7 +104,7 @@ public void visitDetailCodesetCriteriaTest() throws Exception { visitDetail.genderCS = notInCsSelection; // translate to PG - String notInGenderQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable); + String notInGenderQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable, false); notInGenderQuery = notInGenderQuery.replace("#Codesets", RESULTS_SCHEMA + ".codesets"); String translatedNotInGenderQuery = SqlRender.renderSql(SqlTranslate.translateSql(notInGenderQuery, "postgresql"), new String[] {"cdm_database_schema", "indexId"}, @@ -121,7 +121,7 @@ public void visitDetailCodesetCriteriaTest() throws Exception { visitDetail.providerSpecialtyCS = inCsSelection; // translate to PG - String inProviderQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable); + String inProviderQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable, false); inProviderQuery = inProviderQuery.replace("#Codesets", RESULTS_SCHEMA + ".codesets"); String translatedInProviderQuery = SqlRender.renderSql(SqlTranslate.translateSql(inProviderQuery, "postgresql"), new String[] {"cdm_database_schema", "indexId"}, @@ -137,7 +137,7 @@ public void visitDetailCodesetCriteriaTest() throws Exception { visitDetail.providerSpecialtyCS = notInCsSelection; // translate to PG - String notInProviderQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable); + String notInProviderQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable, false); notInProviderQuery = notInProviderQuery.replace("#Codesets", RESULTS_SCHEMA + ".codesets"); String translatedNotInProviderQuery = SqlRender.renderSql(SqlTranslate.translateSql(notInProviderQuery, "postgresql"), new String[] {"cdm_database_schema", "indexId"}, @@ -154,7 +154,7 @@ public void visitDetailCodesetCriteriaTest() throws Exception { visitDetail.placeOfServiceCS = inCsSelection; // translate to PG - String inPlaceOfServiceQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable); + String inPlaceOfServiceQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable, false); inPlaceOfServiceQuery = inPlaceOfServiceQuery.replace("#Codesets", RESULTS_SCHEMA + ".codesets"); String translatedInPlaceOfServiceQuery = SqlRender.renderSql(SqlTranslate.translateSql(inPlaceOfServiceQuery, "postgresql"), new String[] {"cdm_database_schema", "indexId"}, @@ -170,7 +170,7 @@ public void visitDetailCodesetCriteriaTest() throws Exception { visitDetail.placeOfServiceCS = notInCsSelection; // translate to PG - String notInPlaceOfServiceQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable); + String notInPlaceOfServiceQuery = queryBuilder.getCriteriaGroupQuery(cg, eventTable, false); notInPlaceOfServiceQuery = notInPlaceOfServiceQuery.replace("#Codesets", RESULTS_SCHEMA + ".codesets"); String translatedNotInPlaceOfServiceQuery = SqlRender.renderSql(SqlTranslate.translateSql(notInPlaceOfServiceQuery, "postgresql"), new String[] {"cdm_database_schema", "indexId"}, diff --git a/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaQuery_5_0_0_Test.java b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaQuery_5_0_0_Test.java index 4d0e43c5..358ec390 100644 --- a/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaQuery_5_0_0_Test.java +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaQuery_5_0_0_Test.java @@ -111,7 +111,9 @@ public void testConditionEraDateOffset() throws Exception { criteria.codesetId = 1; ConditionEraSqlBuilder builder = new ConditionEraSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("conditionEra.simple", query), new String[]{"person_id", "start_date"})); @@ -119,7 +121,7 @@ public void testConditionEraDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("conditionEra.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -155,7 +157,9 @@ public void testConditionOccurrenceDateOffset() throws Exception { criteria.codesetId = 1; ConditionOccurrenceSqlBuilder builder = new ConditionOccurrenceSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("conditionOccurrence.simple", query), new String[]{"person_id", "start_date"})); @@ -163,7 +167,7 @@ public void testConditionOccurrenceDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("conditionOccurrence.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -199,7 +203,9 @@ public void testDeathDateOffset() throws Exception { criteria.codesetId = 1; DeathSqlBuilder builder = new DeathSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("death.simple", query), new String[]{"person_id", "start_date"})); @@ -207,7 +213,7 @@ public void testDeathDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("death.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -243,7 +249,9 @@ public void testDeviceExposureDateOffset() throws Exception { criteria.codesetId = 1; DeviceExposureSqlBuilder builder = new DeviceExposureSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("deviceExposure.simple", query), new String[]{"person_id", "start_date"})); @@ -251,7 +259,7 @@ public void testDeviceExposureDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("deviceExposure.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -287,7 +295,9 @@ public void testDoseEraDateOffset() throws Exception { criteria.codesetId = 1; DoseEraSqlBuilder builder = new DoseEraSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("doseEra.simple", query), new String[]{"person_id", "start_date"})); @@ -295,7 +305,7 @@ public void testDoseEraDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("doseEra.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -331,7 +341,9 @@ public void testDrugEraDateOffset() throws Exception { criteria.codesetId = 1; DrugEraSqlBuilder builder = new DrugEraSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("drugEra.simple", query), new String[]{"person_id", "start_date"})); @@ -339,7 +351,7 @@ public void testDrugEraDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("drugEra.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -375,7 +387,9 @@ public void testDrugExposureDateOffset() throws Exception { criteria.codesetId = 1; DrugExposureSqlBuilder builder = new DrugExposureSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("drugExposure.simple", query), new String[]{"person_id", "start_date"})); @@ -383,7 +397,7 @@ public void testDrugExposureDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("drugExposure.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -419,7 +433,9 @@ public void testMeasurementDateOffset() throws Exception { criteria.codesetId = 1; MeasurementSqlBuilder builder = new MeasurementSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("measurement.simple", query), new String[]{"person_id", "start_date"})); @@ -427,7 +443,7 @@ public void testMeasurementDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("measurement.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -463,7 +479,9 @@ public void testObservationDateOffset() throws Exception { criteria.codesetId = 1; ObservationSqlBuilder builder = new ObservationSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observation.simple", query), new String[]{"person_id", "start_date"})); @@ -471,7 +489,7 @@ public void testObservationDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observation.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -507,7 +525,9 @@ public void testObservationPeriodDateOffset() throws Exception { ObservationPeriod criteria = new ObservationPeriod(); ObservationPeriodSqlBuilder builder = new ObservationPeriodSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observationPeriod.simple", query), new String[]{"person_id", "start_date"})); @@ -515,7 +535,7 @@ public void testObservationPeriodDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observationPeriod.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -525,7 +545,7 @@ public void testObservationPeriodDateOffset() throws Exception { userPeriod.endDate = "2000-09-30"; criteria.userDefinedPeriod = userPeriod; - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observationPeriod.user_defined", query), new String[]{"person_id", "start_date"})); @@ -560,7 +580,9 @@ public void testPayerPlanPeriodDateOffset() throws Exception { PayerPlanPeriod criteria = new PayerPlanPeriod(); PayerPlanPeriodSqlBuilder builder = new PayerPlanPeriodSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("payerPlanPeriod.simple", query), new String[]{"person_id", "start_date"})); @@ -568,7 +590,7 @@ public void testPayerPlanPeriodDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("payerPlanPeriod.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -578,7 +600,7 @@ public void testPayerPlanPeriodDateOffset() throws Exception { userPeriod.endDate = "2000-09-30"; criteria.userDefinedPeriod = userPeriod; - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("payerPlanPeriod.user_defined", query), new String[]{"person_id", "start_date"})); @@ -614,7 +636,9 @@ public void testProcedureOccurrenceDateOffset() throws Exception { criteria.codesetId = 1; ProcedureOccurrenceSqlBuilder builder = new ProcedureOccurrenceSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("procedureOccurrence.simple", query), new String[]{"person_id", "start_date"})); @@ -622,7 +646,7 @@ public void testProcedureOccurrenceDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("procedureOccurrence.date_adjust", query), new String[]{"person_id", "start_date"})); @@ -659,7 +683,9 @@ public void testVisitOccurrenceDateOffset() throws Exception { criteria.codesetId = 1; VisitOccurrenceSqlBuilder builder = new VisitOccurrenceSqlBuilder<>(); - String query = renderQuery(builder.getCriteriaSql(criteria)); + BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); + String query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("visitOccurrence.simple", query), new String[]{"person_id", "start_date"})); @@ -667,7 +693,7 @@ public void testVisitOccurrenceDateOffset() throws Exception { // Test 2: adjust start and end dates criteria.dateAdjustment = createDateAdjustment(DateAdjustment.DateType.START_DATE, 15, DateAdjustment.DateType.END_DATE, -10); - query = renderQuery(builder.getCriteriaSql(criteria)); + query = renderQuery(builder.getCriteriaSql(criteria, options)); // Store actual records from criteria query into actualTables actualTables.add(new SortedTable(dbUnitCon.createQueryTable("visitOccurrence.date_adjust", query), new String[]{"person_id", "start_date"})); diff --git a/src/test/java/org/ohdsi/circe/cohortdefinition/builders/WindowCriteria_5_0_0_Test.java b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/WindowCriteria_5_0_0_Test.java index 5988a172..0d54db3f 100644 --- a/src/test/java/org/ohdsi/circe/cohortdefinition/builders/WindowCriteria_5_0_0_Test.java +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/WindowCriteria_5_0_0_Test.java @@ -55,6 +55,8 @@ private void performWindowTest(WindowedCriteria wc, String[] verifySets, List additionalColumns) throws Exception { final CohortExpressionQueryBuilder queryBuilder = new CohortExpressionQueryBuilder(); + final BuilderOptions options = new BuilderOptions(); + options.setRetainCohortCovariates(false); // prepare results schema for the specified options.resultSchema prepareSchema(resultsSchema, RESULTS_DDL_PATH); @@ -67,7 +69,7 @@ private void performWindowTest(WindowedCriteria wc, // translate to PG String eventTable = String.format(CriteriaUtils.EVENT_TABLE_TEMPLATE, resultsSchema + ".cohort", "cdm", 1); - String query = queryBuilder.getWindowedCriteriaQuery(wc, eventTable); + String query = queryBuilder.getWindowedCriteriaQuery(wc, eventTable,options); String translatedSql = SqlRender.renderSql(SqlTranslate.translateSql(query, "postgresql"), new String[]{"cdm_database_schema"}, new String[]{"cdm"}); @@ -83,7 +85,6 @@ private void performWindowTest(WindowedCriteria wc, Assertion.assertEquals(expectedTable, actualTable); // requesting additional columns - BuilderOptions options = new BuilderOptions(); options.additionalColumns = additionalColumns; String queryWithColumns = queryBuilder.getWindowedCriteriaQuery(wc, eventTable, options); String translatedWithColumnsSql = SqlRender.renderSql(SqlTranslate.translateSql(queryWithColumns, "postgresql"), diff --git a/src/test/resources/cohortgeneration/allCriteria/allCriteriaExpression.json b/src/test/resources/cohortgeneration/allCriteria/allCriteriaExpression.json index 63fae6f7..f5d4dbe9 100644 --- a/src/test/resources/cohortgeneration/allCriteria/allCriteriaExpression.json +++ b/src/test/resources/cohortgeneration/allCriteria/allCriteriaExpression.json @@ -2197,6 +2197,12 @@ } } ], + "EndStrategy": { + "DateOffset": { + "DateField": "EndDate", + "Offset": 14 + } + }, "CensoringCriteria": [], "CollapseSettings": { "CollapseType": "ERA", diff --git a/src/test/resources/cohortgeneration/allCriteria/criteriaWithDateTime.json b/src/test/resources/cohortgeneration/allCriteria/criteriaWithDateTime.json new file mode 100644 index 00000000..84f7a600 --- /dev/null +++ b/src/test/resources/cohortgeneration/allCriteria/criteriaWithDateTime.json @@ -0,0 +1,190 @@ +{ + "ConceptSets": [ + { + "id": 0, + "name": "Dehydration", + "expression": { + "items": [ + { + "concept": { + "CONCEPT_CLASS_ID": "Clinical Finding", + "CONCEPT_CODE": "34095006", + "CONCEPT_ID": 435796, + "CONCEPT_NAME": "Dehydration", + "DOMAIN_ID": "Condition", + "INVALID_REASON": "V", + "INVALID_REASON_CAPTION": "Valid", + "STANDARD_CONCEPT": "S", + "STANDARD_CONCEPT_CAPTION": "Standard", + "VOCABULARY_ID": "SNOMED" + }, + "includeDescendants": true + } + ] + } + } + ], + "PrimaryCriteria": { + "CriteriaList": [ + { + "ConditionOccurrence": { + "CodesetId": 0 + } + } + ], + "ObservationWindow": { + "PriorDays": 0, + "PostDays": 0 + }, + "PrimaryCriteriaLimit": { + "Type": "All" + } + }, + "QualifiedLimit": { + "Type": "First" + }, + "ExpressionLimit": { + "Type": "All" + }, + "InclusionRules": [ + { + "name": "Measurement", + "expression": { + "Type": "ALL", + "CriteriaList": [ + { + "Criteria": { + "Measurement": {} + }, + "StartWindow": { + "Start": { + "Coeff": -1, + "TimeUnit": "day" + }, + "End": { + "Coeff": 1, + "TimeUnit": "day" + }, + "UseEventEnd": false + }, + "Occurrence": { + "Type": 2, + "Count": 1 + } + } + ], + "DemographicCriteriaList": [], + "Groups": [] + } + }, + { + "name": "Observation", + "expression": { + "Type": "ALL", + "CriteriaList": [ + { + "Criteria": { + "Observation": {} + }, + "StartWindow": { + "Start": { + "Coeff": -1, + "TimeUnit": "day" + }, + "End": { + "Coeff": 1, + "TimeUnit": "day" + }, + "UseEventEnd": false + }, + "Occurrence": { + "Type": 2, + "Count": 1 + } + } + ], + "DemographicCriteriaList": [], + "Groups": [] + } + }, + { + "name": "Visit", + "expression": { + "Type": "ALL", + "CriteriaList": [ + { + "Criteria": { + "VisitOccurrence": {} + }, + "StartWindow": { + "Start": { + "Coeff": -1, + "TimeUnit": "day" + }, + "End": { + "Coeff": 1, + "TimeUnit": "day" + }, + "UseEventEnd": false + }, + "Occurrence": { + "Type": 2, + "Count": 1 + } + } + ], + "DemographicCriteriaList": [], + "Groups": [] + } + }, + { + "name": "Measurement #2", + "expression": { + "Type": "ALL", + "CriteriaList": [ + { + "Criteria": { + "Measurement": { + "IntervalUnit": "minute" + } + }, + "StartWindow": { + "Start": { + "Coeff": -1, + "TimeUnit": "minute" + }, + "End": { + "Coeff": 1, + "TimeUnit": "minute" + }, + "UseEventEnd": false + }, + "Occurrence": { + "Type": 2, + "Count": 1 + } + } + ], + "DemographicCriteriaList": [], + "Groups": [] + } + } + ], + "EndStrategy": { + "DateOffset": { + "DateField": "EndDate", + "Offset": 1, + "OffsetUnitValue": 0, + "OffsetUnit": "day" + } + }, + "CensoringCriteria": [], + "CollapseSettings": { + "CollapseType": "ERA", + "EraPad": 0, + "EraPadUnitValue": 0, + "EraPadUnit": "day" + }, + "CensorWindow": {}, + "cdmVersionRange": ">=5.0.0" + } \ No newline at end of file diff --git a/src/test/resources/criteria/observationDateOffset_PREP.json b/src/test/resources/criteria/observationDateOffset_PREP.json index 3209a36b..ac4de5d0 100644 --- a/src/test/resources/criteria/observationDateOffset_PREP.json +++ b/src/test/resources/criteria/observationDateOffset_PREP.json @@ -21,35 +21,50 @@ "person_id":1, "observation_concept_id":1, "observation_date":"2000-01-01", - "observation_type_concept_id":0 + "observation_type_concept_id":0, + "unit_concept_id": 1, + "value_as_concept_id": 1, + "value_as_number": 1 }, { "observation_id": 2, "person_id":1, "observation_concept_id":1, "observation_date":"2000-06-01", - "observation_type_concept_id":0 + "observation_type_concept_id":0, + "unit_concept_id": 2, + "value_as_concept_id": 2, + "value_as_number": 2 }, { "observation_id": 3, "person_id":1, "observation_concept_id":1, "observation_date":"2000-12-31", - "observation_type_concept_id":0 + "observation_type_concept_id":0, + "unit_concept_id": 2, + "value_as_concept_id": 3, + "value_as_number": 4 }, { "observation_id": 4, "person_id":2, "observation_concept_id":1, "observation_date":"2000-01-01", - "observation_type_concept_id":0 + "observation_type_concept_id":0, + "unit_concept_id": 1, + "value_as_concept_id": 2, + "value_as_number": 3 }, { "observation_id": 5, "person_id":2, "observation_concept_id":1, "observation_date":"2000-12-31", - "observation_type_concept_id":0 + "observation_type_concept_id":0, + "unit_concept_id": 2, + "value_as_concept_id": 1, + "value_as_number": 4 } ], "cdm.observation_period" : [