diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..11a58414 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Matches multiple files with brace expansion notation +# Set default charset +[*.{java,sql}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/pom.xml b/pom.xml index 0ed63906..d0b9e1c5 100644 --- a/pom.xml +++ b/pom.xml @@ -88,25 +88,20 @@ ohdsi repo.ohdsi.org - https://repo.ohdsi.org/nexus/content/repositories/releases - - - ohdsi.thirdparty - repo.ohdsi.org - https://repo.ohdsi.org/nexus/content/repositories/thirdparty - - - ohdsi.snapshots - repo.ohdsi.org-snapshots - https://repo.ohdsi.org/nexus/content/repositories/snapshots - - false - - - true - + https://repo.ohdsi.org/nexus/content/groups/public + + + central + https://repo.maven.apache.org/maven2 + + + ohdsi + repo.ohdsi.org + https://repo.ohdsi.org/nexus/content/groups/public + + com.fasterxml.jackson.core diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionOccurrence.java b/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionOccurrence.java index 281125a0..5a60799e 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionOccurrence.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/ConditionOccurrence.java @@ -47,7 +47,7 @@ public class ConditionOccurrence extends Criteria { public Concept[] conditionType; @JsonProperty("ConditionTypeExclude") - public boolean conditionTypeExclude = false; + public Boolean conditionTypeExclude; @JsonProperty("StopReason") public TextFilter stopReason; diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/Criteria.java b/src/main/java/org/ohdsi/circe/cohortdefinition/Criteria.java index 336e8f0f..dc64997b 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/Criteria.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/Criteria.java @@ -28,7 +28,6 @@ * * @author Chris Knoll */ - @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.WRAPPER_OBJECT) @JsonSubTypes({ @JsonSubTypes.Type(value = ConditionEra.class, name = "ConditionEra"), @@ -49,13 +48,17 @@ @JsonSubTypes.Type(value = PayerPlanPeriod.class, name = "PayerPlanPeriod") }) public abstract class Criteria { + public String accept(IGetCriteriaSqlDispatcher dispatcher) { return this.accept(dispatcher, null); } public abstract String accept(IGetCriteriaSqlDispatcher dispatcher, BuilderOptions options); - @JsonProperty("CorrelatedCriteria") + @JsonProperty("CorrelatedCriteria") public CriteriaGroup CorrelatedCriteria; - + + @JsonProperty("DateAdjustment") + public DateAdjustment dateAdjustment; + } diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/DateAdjustment.java b/src/main/java/org/ohdsi/circe/cohortdefinition/DateAdjustment.java new file mode 100644 index 00000000..4f47f354 --- /dev/null +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/DateAdjustment.java @@ -0,0 +1,43 @@ +/* + * Copyright 2022 cknoll1. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ohdsi.circe.cohortdefinition; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * + * @author cknoll1 + */ +public class DateAdjustment { + + public enum DateType { + @JsonProperty("START_DATE") + START_DATE, + @JsonProperty("END_DATE") + END_DATE + }; + + @JsonProperty("StartWith") + public DateType startWith = DateType.START_DATE; + @JsonProperty("StartOffset") + public int startOffset = 0; + + @JsonProperty("EndWith") + public DateType endWith = DateType.END_DATE; + @JsonProperty("EndOffset") + public int endOffset = 0; + +} diff --git a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/BuilderUtils.java b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/BuilderUtils.java index 5047071c..4aa8dea3 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/BuilderUtils.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/BuilderUtils.java @@ -2,6 +2,7 @@ import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.DateRange; +import org.ohdsi.circe.cohortdefinition.DateAdjustment; import org.ohdsi.circe.cohortdefinition.NumericRange; import org.ohdsi.circe.cohortdefinition.TextFilter; import org.ohdsi.circe.vocabulary.Concept; @@ -9,152 +10,162 @@ import java.util.Locale; import java.util.ArrayList; +import org.ohdsi.circe.helper.ResourceHelper; + public abstract class BuilderUtils { - private final static String CODESET_JOIN_TEMPLATE = "JOIN #Codesets %s on (%s = %s.concept_id and %s.codeset_id = %d)"; + private final static String CODESET_JOIN_TEMPLATE = "JOIN #Codesets %s on (%s = %s.concept_id and %s.codeset_id = %d)"; + private final static String DATE_ADJUSTMENT_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/dateAdjustment.sql"); + ; private final static String STANARD_ALIAS = "cs"; - private final static String NON_STANARD_ALIAS = "cns"; - - public static String getCodesetJoinExpression(Integer standardCodesetId, String standardConceptColumn, Integer sourceCodesetId, String sourceConceptColumn) { + private final static String NON_STANARD_ALIAS = "cns"; - String joinExpression = ""; - ArrayList codesetClauses = new ArrayList<>(); + public static String getDateAdjustmentExpression(DateAdjustment dateAdjustment, String startColumn, String endColumn) { + String expression = StringUtils.replace(DATE_ADJUSTMENT_TEMPLATE, "@startOffset", Integer.toString(dateAdjustment.startOffset)); + expression = StringUtils.replace(expression, "@startColumn", startColumn); + expression = StringUtils.replace(expression, "@endOffset", Integer.toString(dateAdjustment.endOffset)); + expression = StringUtils.replace(expression, "@endColumn", endColumn); + return expression; + } - if (standardCodesetId != null) { - codesetClauses.add(String.format(CODESET_JOIN_TEMPLATE, STANARD_ALIAS, standardConceptColumn, STANARD_ALIAS, STANARD_ALIAS, standardCodesetId)); - } + public static String getCodesetJoinExpression(Integer standardCodesetId, String standardConceptColumn, Integer sourceCodesetId, String sourceConceptColumn) { - // conditionSourceConcept - if (sourceCodesetId != null) { - codesetClauses.add(String.format(CODESET_JOIN_TEMPLATE, NON_STANARD_ALIAS, sourceConceptColumn, NON_STANARD_ALIAS, NON_STANARD_ALIAS, sourceCodesetId)); - } + String joinExpression = ""; + ArrayList codesetClauses = new ArrayList<>(); - if (codesetClauses.size() > 0) { - joinExpression = StringUtils.join(codesetClauses, "\n"); - } + if (standardCodesetId != null) { + codesetClauses.add(String.format(CODESET_JOIN_TEMPLATE, STANARD_ALIAS, standardConceptColumn, STANARD_ALIAS, STANARD_ALIAS, standardCodesetId)); + } + // conditionSourceConcept + if (sourceCodesetId != null) { + codesetClauses.add(String.format(CODESET_JOIN_TEMPLATE, NON_STANARD_ALIAS, sourceConceptColumn, NON_STANARD_ALIAS, NON_STANARD_ALIAS, sourceCodesetId)); + } - return joinExpression; + if (codesetClauses.size() > 0) { + joinExpression = StringUtils.join(codesetClauses, "\n"); } - public static String getOperator(String op) { - - switch (op) { - case "lt": - return "<"; - case "lte": - return "<="; - case "eq": - return "="; - case "!eq": - return "<>"; - case "gt": - return ">"; - case "gte": - return ">="; - } - throw new RuntimeException("Unknown operator type: " + op); + return joinExpression; + } + + public static String getOperator(String op) { + + switch (op) { + case "lt": + return "<"; + case "lte": + return "<="; + case "eq": + return "="; + case "!eq": + return "<>"; + case "gt": + return ">"; + case "gte": + return ">="; } + throw new RuntimeException("Unknown operator type: " + op); + } - public static String getOperator(NumericRange range) { + public static String getOperator(NumericRange range) { - return getOperator(range.op); - } + return getOperator(range.op); + } - public static String getOperator(DateRange range) { + public static String getOperator(DateRange range) { - return getOperator(range.op); - } + return getOperator(range.op); + } - public static String dateStringToSql(String date) { + public static String dateStringToSql(String date) { - String[] dateParts = StringUtils.split(date, '-'); - return String.format("DATEFROMPARTS(%s, %s, %s)", Integer.valueOf(dateParts[0]), Integer.valueOf(dateParts[1]), Integer.valueOf(dateParts[2])); - } + String[] dateParts = StringUtils.split(date, '-'); + return String.format("DATEFROMPARTS(%s, %s, %s)", Integer.valueOf(dateParts[0]), Integer.valueOf(dateParts[1]), Integer.valueOf(dateParts[2])); + } - public static String buildDateRangeClause(String sqlExpression, DateRange range) { - - String clause; - if (range.op.endsWith("bt")) // range with a 'between' op - { - clause = String.format("%s(%s >= %s and %s <= %s)", - range.op.startsWith("!") ? "not " : "", - sqlExpression, - dateStringToSql(range.value), - sqlExpression, - dateStringToSql(range.extent)); - } else // single value range (less than/eq/greater than, etc) - { - clause = String.format("%s %s %s", sqlExpression, getOperator(range), dateStringToSql(range.value)); - } - return clause; - } + public static String buildDateRangeClause(String sqlExpression, DateRange range) { - // assumes decimal range - public static String buildNumericRangeClause(String sqlExpression, NumericRange range, String format) { - - String clause; - if (range.op.endsWith("bt")) { - clause = String.format("%s(%s >= %s and %s <= %s)", - range.op.startsWith("!") ? "not " : "", - sqlExpression, - formatDouble(range.value.doubleValue(), format), - sqlExpression, - formatDouble(range.extent.doubleValue(), format)); - } else { - clause = String.format("%s %s %s", sqlExpression, getOperator(range), formatDouble(range.value.doubleValue(), format)); - } - return clause; + String clause; + if (range.op.endsWith("bt")) // range with a 'between' op + { + clause = String.format("%s(%s >= %s and %s <= %s)", + range.op.startsWith("!") ? "not " : "", + sqlExpression, + dateStringToSql(range.value), + sqlExpression, + dateStringToSql(range.extent)); + } else // single value range (less than/eq/greater than, etc) + { + clause = String.format("%s %s %s", sqlExpression, getOperator(range), dateStringToSql(range.value)); } - - // Assumes integer numeric range - public static String buildNumericRangeClause(String sqlExpression, NumericRange range) { - - String clause; - if (range.op.endsWith("bt")) { - clause = String.format("%s(%s >= %d and %s <= %d)", - range.op.startsWith("!") ? "not " : "", - sqlExpression, - range.value.intValue(), - sqlExpression, - range.extent.intValue()); - } else { - clause = String.format("%s %s %d", sqlExpression, getOperator(range), range.value.intValue()); - } - return clause; + return clause; + } + + // assumes decimal range + public static String buildNumericRangeClause(String sqlExpression, NumericRange range, String format) { + String clause; + if (range.op.endsWith("bt")) { + clause = String.format("%s(%s >= %s and %s <= %s)", + range.op.startsWith("!") ? "not " : "", + sqlExpression, + formatDouble(range.value.doubleValue(), format), + sqlExpression, + formatDouble(range.extent.doubleValue(), format)); + } else { + clause = String.format("%s %s %s", sqlExpression, getOperator(range), formatDouble(range.value.doubleValue(), format)); } + return clause; + } + + // Assumes integer numeric range + public static String buildNumericRangeClause(String sqlExpression, NumericRange range) { + + String clause; + if (range.op.endsWith("bt")) { + clause = String.format("%s(%s >= %d and %s <= %d)", + range.op.startsWith("!") ? "not " : "", + sqlExpression, + range.value.intValue(), + sqlExpression, + range.extent.intValue()); + } else { + clause = String.format("%s %s %d", sqlExpression, getOperator(range), range.value.intValue()); + } + return clause; + } - public static ArrayList getConceptIdsFromConcepts(Concept[] concepts) { + public static ArrayList getConceptIdsFromConcepts(Concept[] concepts) { - ArrayList conceptIdList = new ArrayList<>(); - for (Concept concept : concepts) { - conceptIdList.add(concept.conceptId); - } - return conceptIdList; + ArrayList conceptIdList = new ArrayList<>(); + for (Concept concept : concepts) { + conceptIdList.add(concept.conceptId); } + return conceptIdList; + } - public static String buildTextFilterClause(String sqlExpression, TextFilter filter) { + public static String buildTextFilterClause(String sqlExpression, TextFilter filter) { - String negation = filter.op.startsWith("!") ? "not" : ""; - String prefix = filter.op.endsWith("endsWith") || filter.op.endsWith("contains") ? "%" : ""; - String postfix = filter.op.endsWith("startsWith") || filter.op.endsWith("contains") ? "%" : ""; + String negation = filter.op.startsWith("!") ? "not" : ""; + String prefix = filter.op.endsWith("endsWith") || filter.op.endsWith("contains") ? "%" : ""; + String postfix = filter.op.endsWith("startsWith") || filter.op.endsWith("contains") ? "%" : ""; - String value = escapeSqlParam(filter.text); + String value = escapeSqlParam(filter.text); - return String.format("%s %s like '%s%s%s'", sqlExpression, negation, prefix, value, postfix); - } + return String.format("%s %s like '%s%s%s'", sqlExpression, negation, prefix, value, postfix); + } - private static String escapeSqlParam(String value) { - if (StringUtils.isEmpty(value)) { - return value; - } - return value.replaceAll("\\\\*\\'", "''"); + private static String escapeSqlParam(String value) { + if (StringUtils.isEmpty(value)) { + return value; } - + return value.replaceAll("\\\\*\\'", "''"); + } + private static String formatDouble(double d, String format) { // Forces the US Locale formatting for all double values // for Issue #184: https://github.com/OHDSI/circe-be/issues/184 String formatString = "%" + format; return String.format(Locale.US, formatString, d); } -} + } 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 498be290..4f6183f3 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionEraSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionEraSqlBuilder.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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -20,6 +21,9 @@ public class ConditionEraSqlBuilder extends CriteriaSqlB // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' private final Set DEFAULT_COLUMNS = new HashSet<>(Arrays.asList(CriteriaColumn.START_DATE, CriteriaColumn.END_DATE)); + // 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; @@ -39,7 +43,7 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { case ERA_OCCURRENCES: return "C.condition_occurrence_count"; case DURATION: - return "(DATEDIFF(d,C.condition_era_start_date, C.condition_era_end_date))"; + return "(DATEDIFF(d,C.start_date, C.end_date))"; default: throw new IllegalArgumentException("Invalid CriteriaColumn for Condition Era:" + column.toString()); } @@ -68,6 +72,21 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "ce.condition_era_start_date" : "ce.condition_era_end_date", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "ce.condition_era_start_date" : "ce.condition_era_end_date")); + } else { + selectCols.add("ce.condition_era_start_date as start_date, ce.condition_era_end_date as end_date"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -84,16 +103,16 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // eraStartDate if (criteria.eraStartDate != null) { - whereClauses.add(buildDateRangeClause("C.condition_era_start_date", criteria.eraStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.eraStartDate)); } // eraEndDate if (criteria.eraEndDate != null) { - whereClauses.add(buildDateRangeClause("C.condition_era_end_date", criteria.eraEndDate)); + whereClauses.add(buildDateRangeClause("C.end_date", criteria.eraEndDate)); } // occurrenceCount @@ -103,17 +122,17 @@ protected List resolveWhereClauses(T criteria) { // eraLength if (criteria.eraLength != null) { - whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.condition_era_start_date, C.condition_era_end_date)", criteria.eraLength)); + whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.start_date, C.end_date)", criteria.eraLength)); } // ageAtStart if (criteria.ageAtStart != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.condition_era_start_date) - P.year_of_birth", criteria.ageAtStart)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.ageAtStart)); } // ageAtEnd if (criteria.ageAtEnd != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.condition_era_end_date) - P.year_of_birth", criteria.ageAtEnd)); + whereClauses.add(buildNumericRangeClause("YEAR(C.end_date) - P.year_of_birth", criteria.ageAtEnd)); } // gender 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 14238955..92880b74 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionOccurrenceSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ConditionOccurrenceSqlBuilder.java @@ -8,7 +8,9 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; +import org.ohdsi.circe.cohortdefinition.DateAdjustment; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildDateRangeClause; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -23,6 +25,9 @@ public class ConditionOccurrenceSqlBuilder extend // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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("co.person_id", "co.condition_occurrence_id", "co.condition_concept_id", "co.visit_occurrence_id")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -40,8 +45,8 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { case DOMAIN_CONCEPT: return "C.condition_concept_id"; case DURATION: - return "(DATEDIFF(d,C.condition_start_date, COALESCE(C.condition_end_date, DATEADD(day,1,C.condition_start_date))))"; - default: + return "(DATEDIFF(d,C.start_date, C.end_date))"; + default: throw new IllegalArgumentException("Invalid CriteriaColumn for Condition Occurrence:" + column.toString()); } } @@ -49,12 +54,13 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { @Override protected String embedCodesetClause(String query, T criteria) { - return StringUtils.replace(query, "@codesetClause", - getCodesetJoinExpression(criteria.codesetId, - "co.condition_concept_id", - criteria.conditionSourceConcept, - "co.condition_source_concept_id") - ); + ArrayList joinClauses = new ArrayList<>(); + + joinClauses.add(getCodesetJoinExpression(criteria.codesetId, + "co.condition_concept_id", + criteria.conditionSourceConcept, + "co.condition_source_concept_id")); + return StringUtils.replace(query, "@codesetClause", StringUtils.join(joinClauses, "\n")); } @Override @@ -71,6 +77,36 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + // Condition Type + if (criteria.conditionType != null && criteria.conditionType.length > 0) { + selectCols.add("co.condition_type_concept_id"); + } + // Stop Reason + if (criteria.stopReason != null) { + selectCols.add("co.stop_reason"); + } + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + selectCols.add("co.provider_id"); + } + // conditionStatus + if (criteria.conditionStatus != null && criteria.conditionStatus.length > 0) { + selectCols.add("co.condition_status_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 ? "co.condition_start_date" : "COALESCE(co.condition_end_date, DATEADD(day,1,co.condition_start_date))", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "co.condition_start_date" : "COALESCE(co.condition_end_date, DATEADD(day,1,co.condition_start_date))")); + } 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"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -93,22 +129,22 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // occurrenceStartDate if (criteria.occurrenceStartDate != null) { - whereClauses.add(buildDateRangeClause("C.condition_start_date", criteria.occurrenceStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.occurrenceStartDate)); } // occurrenceEndDate if (criteria.occurrenceEndDate != null) { - whereClauses.add(buildDateRangeClause("C.condition_end_date", criteria.occurrenceEndDate)); + whereClauses.add(buildDateRangeClause("C.end_date", criteria.occurrenceEndDate)); } // conditionType if (criteria.conditionType != null && criteria.conditionType.length > 0) { ArrayList conceptIds = getConceptIdsFromConcepts(criteria.conditionType); - whereClauses.add(String.format("C.condition_type_concept_id %s in (%s)", (criteria.conditionTypeExclude ? "not" : ""), StringUtils.join(conceptIds, ","))); + whereClauses.add(String.format("C.condition_type_concept_id %s in (%s)", (Optional.ofNullable(criteria.conditionTypeExclude).orElse(false) ? "not" : ""), StringUtils.join(conceptIds, ","))); } // Stop Reason @@ -118,7 +154,7 @@ protected List resolveWhereClauses(T criteria) { // age if (criteria.age != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.condition_start_date) - P.year_of_birth", criteria.age)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.age)); } // gender 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 c80901dc..32dd1051 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaSqlBuilder.java @@ -1,5 +1,6 @@ package org.ohdsi.circe.cohortdefinition.builders; +import java.util.ArrayList; import org.apache.commons.lang3.StringUtils; import org.ohdsi.circe.cohortdefinition.Criteria; @@ -19,11 +20,13 @@ public String getCriteriaSql(T criteria, BuilderOptions options) { query = embedCodesetClause(query, criteria); + List selectClauses = resolveSelectClauses(criteria); List joinClauses = resolveJoinClauses(criteria); List whereClauses = resolveWhereClauses(criteria); query = embedOrdinalExpression(query, criteria, whereClauses); + query = embedSelectClauses(query, selectClauses); query = embedJoinClauses(query, joinClauses); query = embedWhereClauses(query, whereClauses); @@ -44,7 +47,7 @@ public String getCriteriaSql(T criteria, BuilderOptions options) { } protected abstract String getTableColumnForCriteriaColumn(CriteriaColumn column); - + protected String getAdditionalColumns(List columns) { String cols = String.join(", ", columns.stream() .map((column) -> { @@ -55,6 +58,10 @@ protected String getAdditionalColumns(List columns) { protected abstract Set getDefaultColumns(); + protected String embedSelectClauses(String query, List selectClauses) { + return StringUtils.replace(query, "@selectClause", StringUtils.join(selectClauses, ",")); + } + protected String embedJoinClauses(String query, List joinClauses) { return StringUtils.replace(query, "@joinClause", StringUtils.join(joinClauses, "\n")); @@ -75,7 +82,20 @@ protected String embedWhereClauses(String query, List whereClauses) { protected abstract String embedOrdinalExpression(String query, T criteria, List whereClauses); + protected List resolveSelectClauses(T criteria) { + return new ArrayList(); + } + protected abstract List resolveJoinClauses(T criteria); - protected abstract List resolveWhereClauses(T criteria); + protected List resolveWhereClauses(T criteria) { + ArrayList whereClauses = new ArrayList<>(); + + // if date is adjusted, the record should only be included if end >= start + if (criteria.dateAdjustment != null) { + whereClauses.add("C.end_date >= C.start_date"); + } + + return whereClauses; + } } 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 0b60eab9..c79fc122 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeathSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DeathSqlBuilder.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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -22,6 +23,9 @@ public class DeathSqlBuilder extends CriteriaSqlBuilder { // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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("d.person_id", "d.cause_concept_id")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -62,6 +66,23 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + // Condition Type + if (criteria.deathType != null && criteria.deathType.length > 0) { + selectCols.add("d.death_type_concept_id"); + } + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, "d.death_date", "DATEADD(day,1,d.death_date)")); + } else { + selectCols.add("d.death_date as start_date, DATEADD(day,1,d.death_date) as end_date"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -78,11 +99,11 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - ArrayList whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // occurrenceStartDate if (criteria.occurrenceStartDate != null) { - whereClauses.add(buildDateRangeClause("C.death_date", criteria.occurrenceStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.occurrenceStartDate)); } // deathType @@ -93,7 +114,7 @@ protected List resolveWhereClauses(T criteria) { // age if (criteria.age != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.death_date) - P.year_of_birth", criteria.age)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.age)); } // gender 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 90040d90..586c15e7 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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -24,6 +25,10 @@ public class DeviceExposureSqlBuilder extends Criteria // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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", + "de.visit_occurrence_id", "de.quantity")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -43,7 +48,7 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { case QUANTITY: return "C.quantity"; case DURATION: - return "DATEDIFF(d,device_exposure_start_date, COALESCE(C.device_exposure_end_date, DATEADD(d,1,C.device_exposure_start_date)))"; + return "DATEDIFF(d,c.start_date, c.end_date)"; default: throw new IllegalArgumentException("Invalid CriteriaColumn for Device Exposure:" + column.toString()); } @@ -73,6 +78,35 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + // Device Type + if (criteria.deviceType != null && criteria.deviceType.length > 0) { + selectCols.add("de.device_type_concept_id"); + } + + // uniqueDeviceId + if (criteria.uniqueDeviceId != null) { + selectCols.add("de.unique_device_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + selectCols.add("de.provider_id"); + } + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "de.device_exposure_start_date" : "COALESCE(de.device_exposure_end_date, DATEADD(day,1,de.device_exposure_start_date))", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "de.device_exposure_start_date" : "COALESCE(de.device_exposure_end_date, DATEADD(day,1,de.device_exposure_start_date))")); + } 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"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -95,16 +129,16 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - ArrayList whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // occurrenceStartDate if (criteria.occurrenceStartDate != null) { - whereClauses.add(buildDateRangeClause("C.device_exposure_start_date", criteria.occurrenceStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.occurrenceStartDate)); } // occurrenceEndDate if (criteria.occurrenceEndDate != null) { - whereClauses.add(buildDateRangeClause("C.device_exposure_end_date", criteria.occurrenceEndDate)); + whereClauses.add(buildDateRangeClause("C.end_date", criteria.occurrenceEndDate)); } // deviceType @@ -125,7 +159,7 @@ protected List resolveWhereClauses(T criteria) { // age if (criteria.age != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.device_exposure_start_date) - P.year_of_birth", criteria.age)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.age)); } // gender 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 40cb05d4..3f473f86 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DoseEraSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DoseEraSqlBuilder.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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -21,6 +22,9 @@ public class DoseEraSqlBuilder extends CriteriaSqlBuilder // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -38,7 +42,7 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { case DOMAIN_CONCEPT: return "C.drug_concept_id"; case DURATION: - return "DATEDIFF(d, C.dose_era_start_date, C.dose_era_end_date)"; + return "DATEDIFF(d, C.start_date, C.end_date)"; case UNIT: return "C.unit_concept_id"; case VALUE_AS_NUMBER: @@ -85,19 +89,36 @@ protected List resolveJoinClauses(T criteria) { return joinClauses; } + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "de.dose_era_start_date" : "de.dose_era_end_date", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "de.dose_era_start_date" : "de.dose_era_end_date")); + } else { + selectCols.add("de.dose_era_start_date as start_date, de.dose_era_end_date as end_date"); + } + + return selectCols; + } + @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // eraStartDate if (criteria.eraStartDate != null) { - whereClauses.add(buildDateRangeClause("C.dose_era_start_date", criteria.eraStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.eraStartDate)); } // eraEndDate if (criteria.eraEndDate != null) { - whereClauses.add(buildDateRangeClause("C.dose_era_end_date", criteria.eraEndDate)); + whereClauses.add(buildDateRangeClause("C.end_date", criteria.eraEndDate)); } // unit @@ -112,17 +133,17 @@ protected List resolveWhereClauses(T criteria) { // eraLength if (criteria.eraLength != null) { - whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.dose_era_start_date, C.dose_era_end_date)", criteria.eraLength)); + whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.start_date, C.end_date)", criteria.eraLength)); } // ageAtStart if (criteria.ageAtStart != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.dose_era_start_date) - P.year_of_birth", criteria.ageAtStart)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.ageAtStart)); } // ageAtEnd if (criteria.ageAtEnd != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.dose_era_end_date) - P.year_of_birth", criteria.ageAtEnd)); + whereClauses.add(buildNumericRangeClause("YEAR(C.end_date) - P.year_of_birth", criteria.ageAtEnd)); } // gender 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 92120c84..acb00829 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugEraSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugEraSqlBuilder.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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -21,6 +22,10 @@ public class DrugEraSqlBuilder extends CriteriaSqlBuilder // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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", + "de.drug_exposure_count", "de.gap_days")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -42,7 +47,7 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { case GAP_DAYS: return "C.gap_days"; case DURATION: - return "DATEDIFF(d,C.drug_era_start_date, C.drug_era_end_date)"; + return "DATEDIFF(d,C.start_date, C.end_date)"; default: throw new IllegalArgumentException("Invalid CriteriaColumn for Drug Era:" + column.toString()); } @@ -71,6 +76,25 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // gap_days and drug_exposure_count are included by default so we do not need to add here + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "de.drug_era_start_date" : "de.drug_era_end_date", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "de.drug_era_start_date" : "de.drug_era_end_date")); + } else { + selectCols.add("de.drug_era_start_date as start_date, de.drug_era_end_date as end_date"); + } + + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -87,16 +111,16 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // eraStartDate if (criteria.eraStartDate != null) { - whereClauses.add(buildDateRangeClause("C.drug_era_start_date", criteria.eraStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.eraStartDate)); } // eraEndDate if (criteria.eraEndDate != null) { - whereClauses.add(buildDateRangeClause("C.drug_era_end_date", criteria.eraEndDate)); + whereClauses.add(buildDateRangeClause("C.end_date", criteria.eraEndDate)); } // occurrenceCount @@ -106,7 +130,7 @@ protected List resolveWhereClauses(T criteria) { // eraLength if (criteria.eraLength != null) { - whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.drug_era_start_date, C.drug_era_end_date)", criteria.eraLength)); + whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.start_date, C.end_date)", criteria.eraLength)); } // gapDays @@ -116,12 +140,12 @@ protected List resolveWhereClauses(T criteria) { // ageAtStart if (criteria.ageAtStart != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.drug_era_start_date) - P.year_of_birth", criteria.ageAtStart)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.ageAtStart)); } // ageAtEnd if (criteria.ageAtEnd != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.drug_era_end_date) - P.year_of_birth", criteria.ageAtEnd)); + whereClauses.add(buildNumericRangeClause("YEAR(C.end_date) - P.year_of_birth", criteria.ageAtEnd)); } // gender 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 2d413fe1..7a4a8045 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugExposureSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/DrugExposureSqlBuilder.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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -23,6 +24,10 @@ public class DrugExposureSqlBuilder extends CriteriaSqlB // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -42,7 +47,7 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { case DOMAIN_CONCEPT: return "C.drug_concept_id"; case DURATION: - return "DATEDIFF(d, C.drug_exposure_start_date, COALESCE(C.drug_exposure_end_date, DATEADD(day,C.days_supply,C.drug_exposure_start_date), DATEADD(day,1,C.drug_exposure_start_date)))"; + return "DATEDIFF(d, C.start_date, C.end_date)"; case QUANTITY: return "C.quantity"; case REFILLS: @@ -77,6 +82,59 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // drugType + if (criteria.drugType != null && criteria.drugType.length > 0) { + selectCols.add("de.drug_type_concept_id"); + } + + // Stop Reason + if (criteria.stopReason != null) { + selectCols.add("de.stop_reason"); + } + + // routeConcept + if (criteria.routeConcept != null && criteria.routeConcept.length > 0) { + selectCols.add("de.route_concept_id"); + } + + // effectiveDrugDose + if (criteria.effectiveDrugDose != null) { + selectCols.add("de.effective_drug_dose"); + } + + // doseUnit + if (criteria.doseUnit != null && criteria.doseUnit.length > 0) { + selectCols.add("de.dose_unit_concept_id"); + } + + // LotNumber + if (criteria.lotNumber != null) { + selectCols.add("de.lot_number"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + selectCols.add("de.provider_id"); + } + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "de.drug_exposure_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))", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "de.drug_exposure_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))")); + } 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"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -99,16 +157,16 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // occurrenceStartDate if (criteria.occurrenceStartDate != null) { - whereClauses.add(buildDateRangeClause("C.drug_exposure_start_date", criteria.occurrenceStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.occurrenceStartDate)); } // occurrenceEndDate if (criteria.occurrenceEndDate != null) { - whereClauses.add(buildDateRangeClause("C.drug_exposure_end_date", criteria.occurrenceEndDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.occurrenceEndDate)); } // drugType @@ -159,7 +217,7 @@ protected List resolveWhereClauses(T criteria) { // age if (criteria.age != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.drug_exposure_start_date) - P.year_of_birth", criteria.age)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.age)); } // gender 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 ffcc320b..fe204467 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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -22,6 +23,10 @@ public class MeasurementSqlBuilder extends CriteriaSqlBui // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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("m.person_id", "m.measurement_id", "m.measurement_concept_id", "m.visit_occurrence_id", + "m.value_as_number", "m.range_high", "m.range_low")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -76,6 +81,48 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // measurementType + if (criteria.measurementType != null && criteria.measurementType.length > 0) { + selectCols.add("m.measurement_type_concept_id"); + } + + // operator + if (criteria.operator != null && criteria.operator.length > 0) { + selectCols.add("m.operator_concept_id"); + } + + // valueAsConcept + if (criteria.valueAsConcept != null && criteria.valueAsConcept.length > 0) { + selectCols.add("m.value_as_concept_id"); + } + + // unit + if (criteria.unit != null && criteria.unit.length > 0) { + selectCols.add("m.unit_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + selectCols.add("m.provider_id"); + } + + // 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)")); + } else { + selectCols.add("m.measurement_date as start_date, DATEADD(day,1,m.measurement_date) as end_date"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -98,11 +145,11 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // occurrenceStartDate if (criteria.occurrenceStartDate != null) { - whereClauses.add(buildDateRangeClause("C.measurement_date", criteria.occurrenceStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.occurrenceStartDate)); } // measurementType @@ -161,7 +208,7 @@ protected List resolveWhereClauses(T criteria) { // age if (criteria.age != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.measurement_date) - P.year_of_birth", criteria.age)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.age)); } // gender 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 4500a584..d403be12 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationPeriodSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationPeriodSqlBuilder.java @@ -10,6 +10,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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -22,6 +23,9 @@ public class ObservationPeriodSqlBuilder extends Cr // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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("op.person_id", "op.observation_period_id", "op.period_type_concept_id")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -35,12 +39,12 @@ public String getCriteriaSql(T criteria, BuilderOptions options) { // overwrite user defined dates in select String startDateExpression = (criteria.userDefinedPeriod != null && criteria.userDefinedPeriod.startDate != null) ? BuilderUtils.dateStringToSql(criteria.userDefinedPeriod.startDate) - : "C.observation_period_start_date"; + : "C.start_date"; query = StringUtils.replace(query, "@startDateExpression", startDateExpression); String endDateExpression = (criteria.userDefinedPeriod != null && criteria.userDefinedPeriod.endDate != null) ? BuilderUtils.dateStringToSql(criteria.userDefinedPeriod.endDate) - : "C.observation_period_end_date"; + : "C.end_date"; query = StringUtils.replace(query, "@endDateExpression", endDateExpression); return query; } @@ -74,6 +78,22 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "op.observation_period_start_date" : "op.observation_period_end_date", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "op.observation_period_start_date" : "op.observation_period_end_date")); + } else { + selectCols.add("op.observation_period_start_date as start_date, op.observation_period_end_date as end_date"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -90,7 +110,7 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); if (criteria.first != null && criteria.first == true) { whereClauses.add("C.ordinal = 1"); @@ -102,23 +122,23 @@ protected List resolveWhereClauses(T criteria) { if (userDefinedPeriod.startDate != null) { String startDateExpression = BuilderUtils.dateStringToSql(userDefinedPeriod.startDate); - whereClauses.add(String.format("C.OBSERVATION_PERIOD_START_DATE <= %s and C.OBSERVATION_PERIOD_END_DATE >= %s", startDateExpression, startDateExpression)); + whereClauses.add(String.format("C.start_date <= %s and C.end_date >= %s", startDateExpression, startDateExpression)); } if (userDefinedPeriod.endDate != null) { String endDateExpression = BuilderUtils.dateStringToSql(userDefinedPeriod.endDate); - whereClauses.add(String.format("C.OBSERVATION_PERIOD_START_DATE <= %s and C.OBSERVATION_PERIOD_END_DATE >= %s", endDateExpression, endDateExpression)); + whereClauses.add(String.format("C.start_date <= %s and C.end_date >= %s", endDateExpression, endDateExpression)); } } // periodStartDate if (criteria.periodStartDate != null) { - whereClauses.add(buildDateRangeClause("C.observation_period_start_date", criteria.periodStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.periodStartDate)); } // periodEndDate if (criteria.periodEndDate != null) { - whereClauses.add(buildDateRangeClause("C.observation_period_end_date", criteria.periodEndDate)); + whereClauses.add(buildDateRangeClause("C.end_date", criteria.periodEndDate)); } // periodType @@ -129,17 +149,17 @@ protected List resolveWhereClauses(T criteria) { // periodLength if (criteria.periodLength != null) { - whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.observation_period_start_date, C.observation_period_end_date)", criteria.periodLength)); + whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.start_date, C.end_date)", criteria.periodLength)); } // ageAtStart if (criteria.ageAtStart != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.observation_period_start_date) - P.year_of_birth", criteria.ageAtStart)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.ageAtStart)); } // ageAtEnd if (criteria.ageAtEnd != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.observation_period_end_date) - P.year_of_birth", criteria.ageAtEnd)); + whereClauses.add(buildNumericRangeClause("YEAR(C.end_date) - P.year_of_birth", criteria.ageAtEnd)); } return whereClauses; 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 ac1fa7c9..5206ef23 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ObservationSqlBuilder.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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -19,21 +20,25 @@ public class ObservationSqlBuilder extends CriteriaSqlBuilder { - private final static String OBSERVATION_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/observation.sql"); + private final static String OBSERVATION_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/observation.sql"); // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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("o.person_id", "o.observation_id", + "o.observation_concept_id", "o.visit_occurrence_id", "o.value_as_number")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; } - @Override - protected String getQueryTemplate() { + @Override + protected String getQueryTemplate() { - return OBSERVATION_TEMPLATE; - } + return OBSERVATION_TEMPLATE; + } @Override protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { @@ -49,114 +54,159 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { } } - @Override - protected String embedCodesetClause(String query, T criteria) { - - return StringUtils.replace(query, "@codesetClause", - getCodesetJoinExpression(criteria.codesetId, - "o.observation_concept_id", - criteria.observationSourceConcept, - "o.observation_source_concept_id") - ); + @Override + protected String embedCodesetClause(String query, T criteria) { + + return StringUtils.replace(query, "@codesetClause", + getCodesetJoinExpression(criteria.codesetId, + "o.observation_concept_id", + criteria.observationSourceConcept, + "o.observation_source_concept_id") + ); + } + + @Override + protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + + // first + if (criteria.first != null && criteria.first) { + whereClauses.add("C.ordinal = 1"); + query = StringUtils.replace(query, "@ordinalExpression", ", row_number() over (PARTITION BY o.person_id ORDER BY o.observation_date, o.observation_id) as ordinal"); + } else { + query = StringUtils.replace(query, "@ordinalExpression", ""); + } + + return query; + } + + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // measurementType + if (criteria.observationType != null && criteria.observationType.length > 0) { + selectCols.add("o.observation_type_concept_id"); } - @Override - protected String embedOrdinalExpression(String query, T criteria, List whereClauses) { + // valueAsString + if (criteria.valueAsString != null) { + selectCols.add("o.value_as_string"); + } - // first - if (criteria.first != null && criteria.first) { - whereClauses.add("C.ordinal = 1"); - query = StringUtils.replace(query, "@ordinalExpression", ", row_number() over (PARTITION BY o.person_id ORDER BY o.observation_date, o.observation_id) as ordinal"); - } else { - query = StringUtils.replace(query, "@ordinalExpression", ""); - } + // valueAsConcept + if (criteria.valueAsConcept != null && criteria.valueAsConcept.length > 0) { + selectCols.add("o.value_as_concept_id"); + } - return query; + // qualifier + if (criteria.qualifier != null && criteria.qualifier.length > 0) { + selectCols.add("o.qualifier_concept_id"); + } + + // unit + 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"); } - @Override - protected List resolveJoinClauses(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 ? "o.observation_date" : "DATEADD(day,1,o.observation_date)", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "o.observation_date" : "DATEADD(day,1,o.observation_date)")); + } else { + selectCols.add("o.observation_date as start_date, DATEADD(day,1,o.observation_date) as end_date"); + } + return selectCols; + } - List joinClauses = new ArrayList<>(); + @Override + protected List resolveJoinClauses(T criteria) { - // join to PERSON - if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) { - joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id"); - } - if (criteria.visitType != null && criteria.visitType.length > 0) { - joinClauses.add("JOIN @cdm_database_schema.VISIT_OCCURRENCE V on C.visit_occurrence_id = V.visit_occurrence_id and C.person_id = V.person_id"); - } - if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { - joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id"); - } + List joinClauses = new ArrayList<>(); - return joinClauses; + // join to PERSON + if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) { + joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id"); + } + if (criteria.visitType != null && criteria.visitType.length > 0) { + joinClauses.add("JOIN @cdm_database_schema.VISIT_OCCURRENCE V on C.visit_occurrence_id = V.visit_occurrence_id and C.person_id = V.person_id"); + } + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id"); } - @Override - protected List resolveWhereClauses(T criteria) { + return joinClauses; + } - List whereClauses = new ArrayList<>(); + @Override + protected List resolveWhereClauses(T criteria) { - // occurrenceStartDate - if (criteria.occurrenceStartDate != null) { - whereClauses.add(buildDateRangeClause("C.observation_date", criteria.occurrenceStartDate)); - } + List whereClauses = super.resolveWhereClauses(criteria); - // measurementType - if (criteria.observationType != null && criteria.observationType.length > 0) { - ArrayList conceptIds = getConceptIdsFromConcepts(criteria.observationType); - whereClauses.add(String.format("C.observation_type_concept_id %s in (%s)", (criteria.observationTypeExclude ? "not" : ""), StringUtils.join(conceptIds, ","))); - } + // occurrenceStartDate + if (criteria.occurrenceStartDate != null) { + whereClauses.add(buildDateRangeClause("C.start_date", criteria.occurrenceStartDate)); + } + + // measurementType + if (criteria.observationType != null && criteria.observationType.length > 0) { + ArrayList conceptIds = getConceptIdsFromConcepts(criteria.observationType); + whereClauses.add(String.format("C.observation_type_concept_id %s in (%s)", (criteria.observationTypeExclude ? "not" : ""), StringUtils.join(conceptIds, ","))); + } - // valueAsNumber - if (criteria.valueAsNumber != null) { - whereClauses.add(buildNumericRangeClause("C.value_as_number", criteria.valueAsNumber, ".4f")); - } + // valueAsNumber + if (criteria.valueAsNumber != null) { + whereClauses.add(buildNumericRangeClause("C.value_as_number", criteria.valueAsNumber, ".4f")); + } - // valueAsString - if (criteria.valueAsString != null) { - whereClauses.add(buildTextFilterClause("C.value_as_string", criteria.valueAsString)); - } + // valueAsString + if (criteria.valueAsString != null) { + whereClauses.add(buildTextFilterClause("C.value_as_string", criteria.valueAsString)); + } - // valueAsConcept - if (criteria.valueAsConcept != null && criteria.valueAsConcept.length > 0) { - ArrayList conceptIds = getConceptIdsFromConcepts(criteria.valueAsConcept); - whereClauses.add(String.format("C.value_as_concept_id in (%s)", StringUtils.join(conceptIds, ","))); - } + // valueAsConcept + if (criteria.valueAsConcept != null && criteria.valueAsConcept.length > 0) { + ArrayList conceptIds = getConceptIdsFromConcepts(criteria.valueAsConcept); + whereClauses.add(String.format("C.value_as_concept_id in (%s)", StringUtils.join(conceptIds, ","))); + } - // qualifier - if (criteria.qualifier != null && criteria.qualifier.length > 0) { - ArrayList conceptIds = getConceptIdsFromConcepts(criteria.qualifier); - whereClauses.add(String.format("C.qualifier_concept_id in (%s)", StringUtils.join(conceptIds, ","))); - } + // qualifier + if (criteria.qualifier != null && criteria.qualifier.length > 0) { + ArrayList conceptIds = getConceptIdsFromConcepts(criteria.qualifier); + whereClauses.add(String.format("C.qualifier_concept_id in (%s)", StringUtils.join(conceptIds, ","))); + } - // unit - if (criteria.unit != null && criteria.unit.length > 0) { - ArrayList conceptIds = getConceptIdsFromConcepts(criteria.unit); - whereClauses.add(String.format("C.unit_concept_id in (%s)", StringUtils.join(conceptIds, ","))); - } + // unit + if (criteria.unit != null && criteria.unit.length > 0) { + ArrayList conceptIds = getConceptIdsFromConcepts(criteria.unit); + whereClauses.add(String.format("C.unit_concept_id in (%s)", StringUtils.join(conceptIds, ","))); + } - // age - if (criteria.age != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.observation_date) - P.year_of_birth", criteria.age)); - } + // age + if (criteria.age != null) { + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.age)); + } - // gender - if (criteria.gender != null && criteria.gender.length > 0) { - whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender), ","))); - } + // gender + if (criteria.gender != null && criteria.gender.length > 0) { + whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender), ","))); + } - // providerSpecialty - if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { - whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty), ","))); - } - - // visitType - if (criteria.visitType != null && criteria.visitType.length > 0) { - whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType), ","))); - } + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty), ","))); + } - return whereClauses; + // visitType + if (criteria.visitType != null && criteria.visitType.length > 0) { + whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType), ","))); } + + 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 ea98b6cb..6b0b5135 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/PayerPlanPeriodSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/PayerPlanPeriodSqlBuilder.java @@ -10,6 +10,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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -22,6 +23,9 @@ public class PayerPlanPeriodSqlBuilder extends Criter // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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("ppp.person_id", "ppp.payer_plan_period_id")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -33,12 +37,12 @@ public String getCriteriaSql(T criteria, BuilderOptions options) { String query = super.getCriteriaSql(criteria, options); String startDateExpression = (criteria.userDefinedPeriod != null && criteria.userDefinedPeriod.startDate != null) ? BuilderUtils.dateStringToSql(criteria.userDefinedPeriod.startDate) - : "C.payer_plan_period_start_date"; + : "C.start_date"; query = StringUtils.replace(query, "@startDateExpression", startDateExpression); String endDateExpression = (criteria.userDefinedPeriod != null && criteria.userDefinedPeriod.endDate != null) ? BuilderUtils.dateStringToSql(criteria.userDefinedPeriod.endDate) - : "C.payer_plan_period_end_date"; + : "C.end_date"; query = StringUtils.replace(query, "@endDateExpression", endDateExpression); return query; } @@ -71,6 +75,61 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // payer concept + if (criteria.payerConcept != null) { + selectCols.add("ppp.payer_concept_id"); + } + + // plan concept + if (criteria.planConcept != null) { + selectCols.add("ppp.plan_concept_id"); + } + + // sponsor concept + if (criteria.sponsorConcept != null) { + selectCols.add("ppp.sponsor_concept_id"); + } + + // stop reason concept + if (criteria.stopReasonConcept != null) { + selectCols.add("ppp.stop_reason_concept_id"); + } + + // payer SourceConcept + if (criteria.payerSourceConcept != null) { + selectCols.add("ppp.payer_source_concept_id"); + } + + // plan SourceConcept + if (criteria.planSourceConcept != null) { + selectCols.add("ppp.plan_source_concept_id"); + } + + // sponsor SourceConcept + if (criteria.sponsorSourceConcept != null) { + selectCols.add("ppp.sponsor_source_concept_id"); + } + + // stop reason SourceConcept + if (criteria.stopReasonSourceConcept != null) { + selectCols.add("ppp.stop_reason_source_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 ? "ppp.payer_plan_period_start_date" : "ppp.payer_plan_period_end_date", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "ppp.payer_plan_period_start_date" : "ppp.payer_plan_period_end_date")); + } else { + selectCols.add("ppp.payer_plan_period_start_date as start_date, ppp.payer_plan_period_end_date as end_date"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -86,7 +145,7 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); //first if (criteria.first != null && criteria.first) { @@ -99,38 +158,38 @@ protected List resolveWhereClauses(T criteria) { if (userDefinedPeriod.startDate != null) { String startDateExpression = BuilderUtils.dateStringToSql(userDefinedPeriod.startDate); - whereClauses.add(String.format("C.PAYER_PLAN_PERIOD_START_DATE <= %s and C.PAYER_PLAN_PERIOD_END_DATE >= %s", startDateExpression, startDateExpression)); + whereClauses.add(String.format("C.start_date <= %s and C.end_date >= %s", startDateExpression, startDateExpression)); } if (userDefinedPeriod.endDate != null) { String endDateExpression = BuilderUtils.dateStringToSql(userDefinedPeriod.endDate); - whereClauses.add(String.format("C.PAYER_PLAN_PERIOD_START_DATE <= %s and C.PAYER_PLAN_PERIOD_END_DATE >= %s", endDateExpression, endDateExpression)); + whereClauses.add(String.format("C.start_date <= %s and C.end_date >= %s", endDateExpression, endDateExpression)); } } //periodStartDate if (criteria.periodStartDate != null) { - whereClauses.add(buildDateRangeClause("C.payer_plan_period_start_date", criteria.periodStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.periodStartDate)); } //periodEndDate if (criteria.periodEndDate != null) { - whereClauses.add(buildDateRangeClause("C.payer_plan_period_end_date", criteria.periodEndDate)); + whereClauses.add(buildDateRangeClause("C.end_date", criteria.periodEndDate)); } //periodLength if (criteria.periodLength != null) { - whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.payer_plan_period_start_date, C.payer_plan_period_end_date)", criteria.periodLength)); + whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.start_date, C.end_date)", criteria.periodLength)); } //ageAtStart if (criteria.ageAtStart != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.payer_plan_period_start_date) - P.year_of_birth", criteria.ageAtStart)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.ageAtStart)); } //ageAtEnd if (criteria.ageAtEnd != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.payer_plan_period_end_date) - P.year_of_birth", criteria.ageAtEnd)); + whereClauses.add(buildNumericRangeClause("YEAR(C.end_date) - P.year_of_birth", criteria.ageAtEnd)); } //gender 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 c8b207cb..b6d30336 100644 --- a/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ProcedureOccurrenceSqlBuilder.java +++ b/src/main/java/org/ohdsi/circe/cohortdefinition/builders/ProcedureOccurrenceSqlBuilder.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; import static org.ohdsi.circe.cohortdefinition.builders.BuilderUtils.buildNumericRangeClause; @@ -22,6 +23,10 @@ public class ProcedureOccurrenceSqlBuilder extend // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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("po.person_id", "po.procedure_occurrence_id", + "po.procedure_concept_id", "po.visit_occurrence_id", "po.quantity")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -71,6 +76,37 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // procedureType + if (criteria.procedureType != null && criteria.procedureType.length > 0) { + selectCols.add("po.procedure_type_concept_id"); + } + + // modifier + if (criteria.modifier != null && criteria.modifier.length > 0) { + selectCols.add("po.modifier_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + selectCols.add("po.provider_id"); + } + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "po.procedure_date" : "DATEADD(day,1,po.procedure_date)", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "po.procedure_date" : "DATEADD(day,1,po.procedure_date)")); + } else { + selectCols.add("po.procedure_date as start_date, DATEADD(day,1,po.procedure_date) as end_date"); + } + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -93,11 +129,11 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // occurrenceStartDate if (criteria.occurrenceStartDate != null) { - whereClauses.add(buildDateRangeClause("C.procedure_date", criteria.occurrenceStartDate)); + whereClauses.add(buildDateRangeClause("C.start_date", criteria.occurrenceStartDate)); } // procedureType @@ -119,7 +155,7 @@ protected List resolveWhereClauses(T criteria) { // age if (criteria.age != null) { - whereClauses.add(buildNumericRangeClause("YEAR(C.procedure_date) - P.year_of_birth", criteria.age)); + whereClauses.add(buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.age)); } // gender 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 23d06f50..893b7cfd 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 { @@ -14,6 +15,10 @@ public class VisitDetailSqlBuilder extends CriteriaSqlBui // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -30,7 +35,7 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { case DOMAIN_CONCEPT: return "C.visit_detail_concept_id"; case DURATION: - return "DATEDIFF(d, C.visit_detail_start_date, C.visit_detail_end_date)"; + return "DATEDIFF(d, C.start_date, C.end_date)"; default: throw new IllegalArgumentException("Invalid CriteriaColumn for Visit Detail:" + column.toString()); } @@ -59,6 +64,38 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // visitType + if (criteria.visitDetailTypeCS != null && criteria.visitDetailTypeCS.codesetId != null) { + selectCols.add("vd.visit_detail_type_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialtyCS != null && criteria.providerSpecialtyCS.codesetId != null) { + selectCols.add("vd.provider_id"); + } + + // placeOfService + if (criteria.placeOfServiceCS != null && criteria.placeOfServiceCS.codesetId != null) { + selectCols.add("vd.care_site_id"); + } + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + 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"); + } + + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -85,16 +122,16 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // occurrenceStartDate if (criteria.visitDetailStartDate != null) { - whereClauses.add(BuilderUtils.buildDateRangeClause("C.visit_detail_start_date", criteria.visitDetailStartDate)); + whereClauses.add(BuilderUtils.buildDateRangeClause("C.start_date", criteria.visitDetailStartDate)); } // occurrenceEndDate if (criteria.visitDetailEndDate != null) { - whereClauses.add(BuilderUtils.buildDateRangeClause("C.visit_detail_end_date", criteria.visitDetailEndDate)); + whereClauses.add(BuilderUtils.buildDateRangeClause("C.end_date", criteria.visitDetailEndDate)); } // visitType @@ -104,12 +141,12 @@ protected List resolveWhereClauses(T criteria) { // visitLength if (criteria.visitDetailLength != null) { - whereClauses.add(BuilderUtils.buildNumericRangeClause("DATEDIFF(d,C.visit_detail_start_date, C.visit_detail_end_date)", criteria.visitDetailLength)); + whereClauses.add(BuilderUtils.buildNumericRangeClause("DATEDIFF(d,C.start_date, C.end_date)", criteria.visitDetailLength)); } // age if (criteria.age != null) { - whereClauses.add(BuilderUtils.buildNumericRangeClause("YEAR(C.visit_detail_start_date) - P.year_of_birth", criteria.age)); + whereClauses.add(BuilderUtils.buildNumericRangeClause("YEAR(C.end_date) - P.year_of_birth", criteria.age)); } // gender 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 e0338530..8780f808 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 { @@ -17,6 +18,9 @@ public class VisitOccurrenceSqlBuilder extends Criter // default columns are those that are specified in the template, and dont' need to be added if specifeid in 'additionalColumns' 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("vo.person_id", "vo.visit_occurrence_id", "vo.visit_concept_id")); + @Override protected Set getDefaultColumns() { return DEFAULT_COLUMNS; @@ -33,7 +37,7 @@ protected String getTableColumnForCriteriaColumn(CriteriaColumn column) { case DOMAIN_CONCEPT: return "C.visit_concept_id"; case DURATION: - return "DATEDIFF(d, C.visit_start_date, C.visit_end_date)"; + return "DATEDIFF(d, C.start_date, C.end_date)"; default: throw new IllegalArgumentException("Invalid CriteriaColumn for Visit Occurrence:" + column.toString()); } @@ -62,6 +66,38 @@ protected String embedOrdinalExpression(String query, T criteria, List w return query; } + @Override + protected List resolveSelectClauses(T criteria) { + + ArrayList selectCols = new ArrayList<>(DEFAULT_SELECT_COLUMNS); + + // visitType + if (criteria.visitType != null && criteria.visitType.length > 0) { + selectCols.add("vo.visit_type_concept_id"); + } + + // providerSpecialty + if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0) { + selectCols.add("vo.provider_id"); + } + + // placeOfService + if (criteria.placeOfService != null && criteria.placeOfService.length > 0) { + selectCols.add("vo.care_site_id"); + } + + // dateAdjustment or default start/end dates + if (criteria.dateAdjustment != null) { + selectCols.add(BuilderUtils.getDateAdjustmentExpression(criteria.dateAdjustment, + criteria.dateAdjustment.startWith == DateAdjustment.DateType.START_DATE ? "vo.visit_start_date" : "vo.visit_end_date", + criteria.dateAdjustment.endWith == DateAdjustment.DateType.START_DATE ? "vo.visit_start_date" : "vo.visit_end_date")); + } else { + selectCols.add("vo.visit_start_date as start_date, vo.visit_end_date as end_date"); + } + + return selectCols; + } + @Override protected List resolveJoinClauses(T criteria) { @@ -88,16 +124,16 @@ protected List resolveJoinClauses(T criteria) { @Override protected List resolveWhereClauses(T criteria) { - List whereClauses = new ArrayList<>(); + List whereClauses = super.resolveWhereClauses(criteria); // occurrenceStartDate if (criteria.occurrenceStartDate != null) { - whereClauses.add(BuilderUtils.buildDateRangeClause("C.visit_start_date", criteria.occurrenceStartDate)); + whereClauses.add(BuilderUtils.buildDateRangeClause("C.start_date", criteria.occurrenceStartDate)); } // occurrenceEndDate if (criteria.occurrenceEndDate != null) { - whereClauses.add(BuilderUtils.buildDateRangeClause("C.visit_end_date", criteria.occurrenceEndDate)); + whereClauses.add(BuilderUtils.buildDateRangeClause("C.end_date", criteria.occurrenceEndDate)); } // visitType @@ -108,12 +144,12 @@ protected List resolveWhereClauses(T criteria) { // visitLength if (criteria.visitLength != null) { - whereClauses.add(BuilderUtils.buildNumericRangeClause("DATEDIFF(d,C.visit_start_date, C.visit_end_date)", criteria.visitLength)); + whereClauses.add(BuilderUtils.buildNumericRangeClause("DATEDIFF(d,C.start_date, C.end_date)", criteria.visitLength)); } // age if (criteria.age != null) { - whereClauses.add(BuilderUtils.buildNumericRangeClause("YEAR(C.visit_start_date) - P.year_of_birth", criteria.age)); + whereClauses.add(BuilderUtils.buildNumericRangeClause("YEAR(C.start_date) - P.year_of_birth", criteria.age)); } // gender diff --git a/src/main/java/org/ohdsi/circe/vocabulary/ConceptSetExpression.java b/src/main/java/org/ohdsi/circe/vocabulary/ConceptSetExpression.java index 163d0ccc..7d174320 100644 --- a/src/main/java/org/ohdsi/circe/vocabulary/ConceptSetExpression.java +++ b/src/main/java/org/ohdsi/circe/vocabulary/ConceptSetExpression.java @@ -34,6 +34,7 @@ public class ConceptSetExpression { private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); public static class ConceptSetItem { + public Concept concept; public boolean isExcluded; public boolean includeDescendants; @@ -49,8 +50,8 @@ public boolean equals(Object o) { } ConceptSetItem other = (ConceptSetItem) o; return Objects.equals(concept, other.concept) && Objects.equals(isExcluded, other.isExcluded) - && Objects.equals(includeDescendants, other.includeDescendants) - && Objects.equals(includeMapped, other.includeMapped); + && Objects.equals(includeDescendants, other.includeDescendants) + && Objects.equals(includeMapped, other.includeMapped); } @Override @@ -79,6 +80,6 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(items); + return Objects.hash((Object[]) items); } } diff --git a/src/main/resources/resources/cohortdefinition/sql/conditionEra.sql b/src/main/resources/resources/cohortdefinition/sql/conditionEra.sql index f346e359..15246416 100644 --- a/src/main/resources/resources/cohortdefinition/sql/conditionEra.sql +++ b/src/main/resources/resources/cohortdefinition/sql/conditionEra.sql @@ -1,10 +1,9 @@ -- Begin Condition Era Criteria -select C.person_id, C.condition_era_id as event_id, C.condition_era_start_date as start_date, - C.condition_era_end_date as end_date, CAST(NULL as bigint) as visit_occurrence_id, - C.condition_era_start_date as sort_date@additionalColumns +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 from ( - select ce.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.CONDITION_ERA ce @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/conditionOccurrence.sql b/src/main/resources/resources/cohortdefinition/sql/conditionOccurrence.sql index 0cdda42e..2c423923 100644 --- a/src/main/resources/resources/cohortdefinition/sql/conditionOccurrence.sql +++ b/src/main/resources/resources/cohortdefinition/sql/conditionOccurrence.sql @@ -1,9 +1,9 @@ -- Begin Condition Occurrence Criteria -SELECT C.person_id, C.condition_occurrence_id as event_id, C.condition_start_date as start_date, COALESCE(C.condition_end_date, DATEADD(day,1,C.condition_start_date)) as end_date, - C.visit_occurrence_id, C.condition_start_date as sort_date@additionalColumns +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 FROM ( - SELECT co.* @ordinalExpression + SELECT @selectClause @ordinalExpression FROM @cdm_database_schema.CONDITION_OCCURRENCE co @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/dateAdjustment.sql b/src/main/resources/resources/cohortdefinition/sql/dateAdjustment.sql new file mode 100644 index 00000000..b8d9a89e --- /dev/null +++ b/src/main/resources/resources/cohortdefinition/sql/dateAdjustment.sql @@ -0,0 +1 @@ +DATEADD(day,@startOffset,@startColumn) as start_date, DATEADD(day,@endOffset,@endColumn) as end_date \ No newline at end of file diff --git a/src/main/resources/resources/cohortdefinition/sql/death.sql b/src/main/resources/resources/cohortdefinition/sql/death.sql index b7d021d3..e97267aa 100644 --- a/src/main/resources/resources/cohortdefinition/sql/death.sql +++ b/src/main/resources/resources/cohortdefinition/sql/death.sql @@ -1,9 +1,9 @@ -- Begin Death Criteria -select C.person_id, C.person_id as event_id, C.death_date as start_date, DATEADD(d,1,C.death_date) as end_date, - CAST(NULL as bigint) as visit_occurrence_id, C.death_date as sort_date@additionalColumns +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 from ( - select d.* + select @selectClause FROM @cdm_database_schema.DEATH d @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/deviceExposure.sql b/src/main/resources/resources/cohortdefinition/sql/deviceExposure.sql index 14fc4741..d92a520c 100644 --- a/src/main/resources/resources/cohortdefinition/sql/deviceExposure.sql +++ b/src/main/resources/resources/cohortdefinition/sql/deviceExposure.sql @@ -1,9 +1,9 @@ -- Begin Device Exposure Criteria -select C.person_id, C.device_exposure_id as event_id, C.device_exposure_start_date as start_date, COALESCE(C.device_exposure_end_date, DATEADD(day,1,C.device_exposure_start_date)) as end_date, - C.visit_occurrence_id, C.device_exposure_start_date as sort_date@additionalColumns +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 from ( - select de.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.DEVICE_EXPOSURE de @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/doseEra.sql b/src/main/resources/resources/cohortdefinition/sql/doseEra.sql index 3e7cb5a1..30e54b91 100644 --- a/src/main/resources/resources/cohortdefinition/sql/doseEra.sql +++ b/src/main/resources/resources/cohortdefinition/sql/doseEra.sql @@ -1,9 +1,9 @@ -- Begin Dose Era Criteria -select C.person_id, C.dose_era_id as event_id, C.dose_era_start_date as start_date, C.dose_era_end_date as end_date, - CAST(NULL as bigint) as visit_occurrence_id,C.dose_era_start_date as sort_date@additionalColumns +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 from ( - select de.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.DOSE_ERA de @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/drugEra.sql b/src/main/resources/resources/cohortdefinition/sql/drugEra.sql index 59fe5817..0e163dad 100644 --- a/src/main/resources/resources/cohortdefinition/sql/drugEra.sql +++ b/src/main/resources/resources/cohortdefinition/sql/drugEra.sql @@ -1,9 +1,9 @@ -- Begin Drug Era Criteria -select C.person_id, C.drug_era_id as event_id, C.drug_era_start_date as start_date, C.drug_era_end_date as end_date, - CAST(NULL as bigint) as visit_occurrence_id,C.drug_era_start_date as sort_date@additionalColumns +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 from ( - select de.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.DRUG_ERA de @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/drugExposure.sql b/src/main/resources/resources/cohortdefinition/sql/drugExposure.sql index ca21d18d..930eec6c 100644 --- a/src/main/resources/resources/cohortdefinition/sql/drugExposure.sql +++ b/src/main/resources/resources/cohortdefinition/sql/drugExposure.sql @@ -1,10 +1,9 @@ -- Begin Drug Exposure Criteria -select C.person_id, C.drug_exposure_id as event_id, C.drug_exposure_start_date as start_date, - COALESCE(C.DRUG_EXPOSURE_END_DATE, DATEADD(day,C.DAYS_SUPPLY,DRUG_EXPOSURE_START_DATE), DATEADD(day,1,C.DRUG_EXPOSURE_START_DATE)) as end_date, - C.visit_occurrence_id,C.drug_exposure_start_date as sort_date@additionalColumns +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 from ( - select de.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.DRUG_EXPOSURE de @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/measurement.sql b/src/main/resources/resources/cohortdefinition/sql/measurement.sql index 6a4f060c..f3064700 100644 --- a/src/main/resources/resources/cohortdefinition/sql/measurement.sql +++ b/src/main/resources/resources/cohortdefinition/sql/measurement.sql @@ -1,9 +1,9 @@ -- Begin Measurement Criteria -select C.person_id, C.measurement_id as event_id, C.measurement_date as start_date, DATEADD(d,1,C.measurement_date) as END_DATE, - C.visit_occurrence_id, C.measurement_date as sort_date@additionalColumns +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 from ( - select m.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.MEASUREMENT m @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/observation.sql b/src/main/resources/resources/cohortdefinition/sql/observation.sql index 098a915d..a3381072 100644 --- a/src/main/resources/resources/cohortdefinition/sql/observation.sql +++ b/src/main/resources/resources/cohortdefinition/sql/observation.sql @@ -1,9 +1,9 @@ -- Begin Observation Criteria -select C.person_id, C.observation_id as event_id, C.observation_date as start_date, DATEADD(d,1,C.observation_date) as END_DATE, - C.visit_occurrence_id, C.observation_date as sort_date@additionalColumns +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 from ( - select o.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.OBSERVATION o @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/observationPeriod.sql b/src/main/resources/resources/cohortdefinition/sql/observationPeriod.sql index 25ae23c6..e93c8d84 100644 --- a/src/main/resources/resources/cohortdefinition/sql/observationPeriod.sql +++ b/src/main/resources/resources/cohortdefinition/sql/observationPeriod.sql @@ -1,11 +1,11 @@ -- 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.observation_period_start_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns from ( - select op.*, row_number() over (PARTITION BY op.person_id ORDER BY op.observation_period_start_date) as ordinal - FROM @cdm_database_schema.OBSERVATION_PERIOD op + select @selectClause , row_number() over (PARTITION BY op.person_id ORDER BY op.observation_period_start_date) as ordinal + FROM @cdm_database_schema.OBSERVATION_PERIOD op ) C @joinClause @whereClause diff --git a/src/main/resources/resources/cohortdefinition/sql/payerPlanPeriod.sql b/src/main/resources/resources/cohortdefinition/sql/payerPlanPeriod.sql index aa68f5fc..ce96290b 100644 --- a/src/main/resources/resources/cohortdefinition/sql/payerPlanPeriod.sql +++ b/src/main/resources/resources/cohortdefinition/sql/payerPlanPeriod.sql @@ -1,10 +1,10 @@ -- 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.payer_plan_period_start_date as sort_date@additionalColumns + CAST(NULL as bigint) as visit_occurrence_id, C.start_date as sort_date@additionalColumns from ( - select ppp.*, row_number() over (PARTITION BY ppp.person_id ORDER BY ppp.payer_plan_period_start_date) as ordinal + select @selectClause , row_number() over (PARTITION BY ppp.person_id ORDER BY ppp.payer_plan_period_start_date) as ordinal FROM @cdm_database_schema.PAYER_PLAN_PERIOD ppp ) C @joinClause diff --git a/src/main/resources/resources/cohortdefinition/sql/procedureOccurrence.sql b/src/main/resources/resources/cohortdefinition/sql/procedureOccurrence.sql index 61a7bb44..aeb4f79e 100644 --- a/src/main/resources/resources/cohortdefinition/sql/procedureOccurrence.sql +++ b/src/main/resources/resources/cohortdefinition/sql/procedureOccurrence.sql @@ -1,9 +1,9 @@ -- Begin Procedure Occurrence Criteria -select C.person_id, C.procedure_occurrence_id as event_id, C.procedure_date as start_date, DATEADD(d,1,C.procedure_date) as END_DATE, - C.visit_occurrence_id, C.procedure_date as sort_date@additionalColumns +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 from ( - select po.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.PROCEDURE_OCCURRENCE po @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/visitDetail.sql b/src/main/resources/resources/cohortdefinition/sql/visitDetail.sql index 0e342da0..569c1beb 100644 --- a/src/main/resources/resources/cohortdefinition/sql/visitDetail.sql +++ b/src/main/resources/resources/cohortdefinition/sql/visitDetail.sql @@ -1,9 +1,9 @@ -- Begin Visit Detail Criteria -select C.person_id, C.visit_detail_id as event_id, C.visit_detail_start_date as start_date, C.visit_detail_end_date as end_date, - C.visit_occurrence_id, C.visit_detail_start_date as sort_date@additionalColumns +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 from ( - select vd.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.VISIT_DETAIL vd @codesetClause ) C diff --git a/src/main/resources/resources/cohortdefinition/sql/visitOccurrence.sql b/src/main/resources/resources/cohortdefinition/sql/visitOccurrence.sql index 8498da47..56c6d0f4 100644 --- a/src/main/resources/resources/cohortdefinition/sql/visitOccurrence.sql +++ b/src/main/resources/resources/cohortdefinition/sql/visitOccurrence.sql @@ -1,9 +1,9 @@ -- Begin Visit Occurrence Criteria -select C.person_id, C.visit_occurrence_id as event_id, C.visit_start_date as start_date, C.visit_end_date as end_date, - C.visit_occurrence_id, C.visit_start_date as sort_date@additionalColumns +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 from ( - select vo.* @ordinalExpression + select @selectClause @ordinalExpression FROM @cdm_database_schema.VISIT_OCCURRENCE vo @codesetClause ) C 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 e9b0f216..06d8652a 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 @@ -96,7 +96,7 @@ public void loadTestData() throws SQLException, DataSetException { - @Test + @Test public void rawJsonTest() throws SQLException { final CohortExpressionQueryBuilder.BuildExpressionQueryOptions options = buildExpressionQueryOptions(1,"allCriteriaTest"); diff --git a/src/test/java/org/ohdsi/circe/cohortdefinition/SerializeTest.java b/src/test/java/org/ohdsi/circe/cohortdefinition/SerializeTest.java new file mode 100644 index 00000000..4a4c7f46 --- /dev/null +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/SerializeTest.java @@ -0,0 +1,26 @@ +package org.ohdsi.circe.cohortdefinition; + +import org.junit.Test; +import org.ohdsi.circe.BaseTest; +import org.ohdsi.analysis.Utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class SerializeTest extends BaseTest { + + /** + * Check serialization + * + */ + @Test + public void serializeConditionOccurrence() { + + String json = Utils.serialize(new ConditionOccurrence()); + + assertEquals("{\"ConditionOccurrence\":{}}", json); + + ConditionOccurrence co = Utils.deserialize("{\"ConditionOccurrence\":{}}", ConditionOccurrence.class); + assertTrue(true); + } +} 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 new file mode 100644 index 00000000..4d0e43c5 --- /dev/null +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaQuery_5_0_0_Test.java @@ -0,0 +1,684 @@ +/* + * Copyright 2022 cknoll1. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ohdsi.circe.cohortdefinition.builders; + +import com.github.mjeanroy.dbunit.core.dataset.DataSetFactory; +import java.util.ArrayList; +import org.apache.commons.lang3.StringUtils; +import org.dbunit.Assertion; +import org.dbunit.database.IDatabaseConnection; +import org.dbunit.dataset.CompositeDataSet; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.SortedTable; +import org.dbunit.operation.DatabaseOperation; +import org.junit.BeforeClass; +import org.junit.Test; +import org.ohdsi.circe.AbstractDatabaseTest; +import org.ohdsi.circe.cohortdefinition.ConditionEra; +import org.ohdsi.circe.cohortdefinition.ConditionOccurrence; +import org.ohdsi.circe.cohortdefinition.DateAdjustment; +import org.ohdsi.circe.cohortdefinition.Death; +import org.ohdsi.circe.cohortdefinition.DeviceExposure; +import org.ohdsi.circe.cohortdefinition.DoseEra; +import org.ohdsi.circe.cohortdefinition.DrugEra; +import org.ohdsi.circe.cohortdefinition.DrugExposure; +import org.ohdsi.circe.cohortdefinition.Measurement; +import org.ohdsi.circe.cohortdefinition.Observation; +import org.ohdsi.circe.cohortdefinition.ObservationPeriod; +import org.ohdsi.circe.cohortdefinition.PayerPlanPeriod; +import org.ohdsi.circe.cohortdefinition.Period; +import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence; +import org.ohdsi.circe.cohortdefinition.VisitOccurrence; +import org.ohdsi.sql.SqlRender; +import org.ohdsi.sql.SqlTranslate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +/** + * + * @author cknoll1 + */ +public class CriteriaQuery_5_0_0_Test extends AbstractDatabaseTest { + + private final static Logger log = LoggerFactory.getLogger(CriteriaQuery_5_0_0_Test.class); + private static final String CDM_DDL_PATH = "/ddl/cdm_v5.0.sql"; + private static final String TEMP_DDL_PATH = "/criteria/temp.sql"; + + private String renderQuery(String query) { + String result = StringUtils.replace(query, "#Codesets", "temp.codesets"); + return SqlRender.renderSql(SqlTranslate.translateSql(result, "postgresql"), + new String[]{"cdm_database_schema", "vocabulary_database_schema"}, + new String[]{"cdm", "cdm"}); + } + + private DateAdjustment createDateAdjustment(DateAdjustment.DateType startWith, + int startOffset, + DateAdjustment.DateType endWith, + int endOffset) { + DateAdjustment dateAdjustment = new DateAdjustment(); + dateAdjustment.startWith = startWith; + dateAdjustment.startOffset = startOffset; + dateAdjustment.endWith = endWith; + dateAdjustment.endOffset = endOffset; + + return dateAdjustment; + } + @BeforeClass + public static void beforeClass() { + jdbcTemplate = new JdbcTemplate(getDataSource()); + prepareSchema("cdm", CDM_DDL_PATH); + prepareSchema("temp", TEMP_DDL_PATH); + } + + @Test + public void cdmSchemaWasCreated() { + jdbcTemplate.queryForList("select count(*) as c from cdm.PERSON"); + } + + @Test + public void testConditionEraDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/conditionEraDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + ConditionEra criteria = new ConditionEra(); + criteria.codesetId = 1; + + ConditionEraSqlBuilder builder = new ConditionEraSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("conditionEra.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("conditionEra.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/conditionEraDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testConditionOccurrenceDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/conditionOccurrenceDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + ConditionOccurrence criteria = new ConditionOccurrence(); + criteria.codesetId = 1; + + ConditionOccurrenceSqlBuilder builder = new ConditionOccurrenceSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("conditionOccurrence.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("conditionOccurrence.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/conditionOccurrenceDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testDeathDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/deathDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + Death criteria = new Death(); + criteria.codesetId = 1; + + DeathSqlBuilder builder = new DeathSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("death.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("death.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/deathDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testDeviceExposureDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/deviceExposureDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + DeviceExposure criteria = new DeviceExposure(); + criteria.codesetId = 1; + + DeviceExposureSqlBuilder builder = new DeviceExposureSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("deviceExposure.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("deviceExposure.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/deviceExposureDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testDoseEraDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/doseEraDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + DoseEra criteria = new DoseEra(); + criteria.codesetId = 1; + + DoseEraSqlBuilder builder = new DoseEraSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("doseEra.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("doseEra.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/doseEraDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testDrugEraDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/drugEraDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + DrugEra criteria = new DrugEra(); + criteria.codesetId = 1; + + DrugEraSqlBuilder builder = new DrugEraSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("drugEra.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("drugEra.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/drugEraDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testDrugExposureDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/drugExposureDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + DrugExposure criteria = new DrugExposure(); + criteria.codesetId = 1; + + DrugExposureSqlBuilder builder = new DrugExposureSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("drugExposure.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("drugExposure.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/drugExposureDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testMeasurementDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/measurementDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + Measurement criteria = new Measurement(); + criteria.codesetId = 1; + + MeasurementSqlBuilder builder = new MeasurementSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("measurement.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("measurement.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/measurementDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testObservationDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/observationDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + Observation criteria = new Observation(); + criteria.codesetId = 1; + + ObservationSqlBuilder builder = new ObservationSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observation.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observation.date_adjust", query), new String[]{"person_id", "start_date"})); + + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/observationDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testObservationPeriodDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/observationPeriodDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + ObservationPeriod criteria = new ObservationPeriod(); + + ObservationPeriodSqlBuilder builder = new ObservationPeriodSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observationPeriod.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observationPeriod.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Test 3: user-defined start and end dates + Period userPeriod = new Period(); + userPeriod.startDate = "2000-09-01"; + userPeriod.endDate = "2000-09-30"; + criteria.userDefinedPeriod = userPeriod; + + query = renderQuery(builder.getCriteriaSql(criteria)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("observationPeriod.user_defined", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/observationPeriodDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testPayerPlanPeriodDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/payerPlanPeriodDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + PayerPlanPeriod criteria = new PayerPlanPeriod(); + + PayerPlanPeriodSqlBuilder builder = new PayerPlanPeriodSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("payerPlanPeriod.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("payerPlanPeriod.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Test 3: user-defined start and end dates + Period userPeriod = new Period(); + userPeriod.startDate = "2000-09-01"; + userPeriod.endDate = "2000-09-30"; + criteria.userDefinedPeriod = userPeriod; + + query = renderQuery(builder.getCriteriaSql(criteria)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("payerPlanPeriod.user_defined", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/payerPlanPeriodDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testProcedureOccurrenceDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/procedureOccurrenceDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + ProcedureOccurrence criteria = new ProcedureOccurrence(); + criteria.codesetId = 1; + + ProcedureOccurrenceSqlBuilder builder = new ProcedureOccurrenceSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("procedureOccurrence.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("procedureOccurrence.date_adjust", query), new String[]{"person_id", "start_date"})); + + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/procedureOccurrenceDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } + + @Test + public void testVisitOccurrenceDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/visitOccurrenceDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + VisitOccurrence criteria = new VisitOccurrence(); + criteria.codesetId = 1; + + VisitOccurrenceSqlBuilder builder = new VisitOccurrenceSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("visitOccurrence.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("visitOccurrence.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/visitOccurrenceDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } +} diff --git a/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaQuery_5_3_0_Test.java b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaQuery_5_3_0_Test.java new file mode 100644 index 00000000..3c3c8f41 --- /dev/null +++ b/src/test/java/org/ohdsi/circe/cohortdefinition/builders/CriteriaQuery_5_3_0_Test.java @@ -0,0 +1,137 @@ +/* + * Copyright 2022 cknoll1. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ohdsi.circe.cohortdefinition.builders; + +import com.github.mjeanroy.dbunit.core.dataset.DataSetFactory; +import java.util.ArrayList; +import org.apache.commons.lang3.StringUtils; +import org.dbunit.Assertion; +import org.dbunit.database.IDatabaseConnection; +import org.dbunit.dataset.CompositeDataSet; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.SortedTable; +import org.dbunit.operation.DatabaseOperation; +import org.junit.BeforeClass; +import org.junit.Test; +import org.ohdsi.circe.AbstractDatabaseTest; +import org.ohdsi.circe.cohortdefinition.ConditionEra; +import org.ohdsi.circe.cohortdefinition.ConditionOccurrence; +import org.ohdsi.circe.cohortdefinition.DateAdjustment; +import org.ohdsi.circe.cohortdefinition.Death; +import org.ohdsi.circe.cohortdefinition.DeviceExposure; +import org.ohdsi.circe.cohortdefinition.DoseEra; +import org.ohdsi.circe.cohortdefinition.DrugEra; +import org.ohdsi.circe.cohortdefinition.DrugExposure; +import org.ohdsi.circe.cohortdefinition.Measurement; +import org.ohdsi.circe.cohortdefinition.Observation; +import org.ohdsi.circe.cohortdefinition.ObservationPeriod; +import org.ohdsi.circe.cohortdefinition.PayerPlanPeriod; +import org.ohdsi.circe.cohortdefinition.Period; +import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence; +import org.ohdsi.circe.cohortdefinition.VisitDetail; +import org.ohdsi.circe.cohortdefinition.VisitOccurrence; +import org.ohdsi.sql.SqlRender; +import org.ohdsi.sql.SqlTranslate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; + +/** + * + * @author cknoll1 + */ +public class CriteriaQuery_5_3_0_Test extends AbstractDatabaseTest { + + private final static Logger log = LoggerFactory.getLogger(CriteriaQuery_5_3_0_Test.class); + private static final String CDM_DDL_PATH = "/ddl/cdm_v5.3.sql"; + private static final String TEMP_DDL_PATH = "/criteria/temp.sql"; + + private String renderQuery(String query) { + String result = StringUtils.replace(query, "#Codesets", "temp.codesets"); + return SqlRender.renderSql(SqlTranslate.translateSql(result, "postgresql"), + new String[]{"cdm_database_schema", "vocabulary_database_schema"}, + new String[]{"cdm", "cdm"}); + } + + private DateAdjustment createDateAdjustment(DateAdjustment.DateType startWith, + int startOffset, + DateAdjustment.DateType endWith, + int endOffset) { + DateAdjustment dateAdjustment = new DateAdjustment(); + dateAdjustment.startWith = startWith; + dateAdjustment.startOffset = startOffset; + dateAdjustment.endWith = endWith; + dateAdjustment.endOffset = endOffset; + + return dateAdjustment; + } + @BeforeClass + public static void beforeClass() { + jdbcTemplate = new JdbcTemplate(getDataSource()); + prepareSchema("cdm", CDM_DDL_PATH); + prepareSchema("temp", TEMP_DDL_PATH); + } + + @Test + public void cdmSchemaWasCreated() { + jdbcTemplate.queryForList("select count(*) as c from cdm.PERSON"); + } + + @Test + public void testVisitDetailDateOffset() throws Exception { + final String[] testDataSetsPrep = new String[]{ + "/datasets/vocabulary.json", + "/criteria/codesets.json", + "/criteria/visitDetailDateOffset_PREP.json" + }; + final IDatabaseConnection dbUnitCon = getConnection(); + + // load test data into DB. + final IDataSet dsPrep = DataSetFactory.createDataSet(testDataSetsPrep); + DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dsPrep); // clean load of the DB. Careful, clean means "delete the old stuff" + + // capture results in an ArrayList + ArrayList actualTables = new ArrayList<>(); + + // Test 1: simple query with no special conditions + VisitDetail criteria = new VisitDetail(); + criteria.codesetId = 1; + + VisitDetailSqlBuilder builder = new VisitDetailSqlBuilder<>(); + String query = renderQuery(builder.getCriteriaSql(criteria)); + + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("visitDetail.simple", query), new String[]{"person_id", "start_date"})); + + // 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)); + // Store actual records from criteria query into actualTables + actualTables.add(new SortedTable(dbUnitCon.createQueryTable("visitDetail.date_adjust", query), new String[]{"person_id", "start_date"})); + + // Validate results: + final IDataSet actualDataSet = new CompositeDataSet(actualTables.toArray(new ITable[]{})); // put actual results into a CompositeDataSet + + // Load expected data from an XML dataset + final String[] testDataSetsVerify = new String[]{"/criteria/visitDetailDateOffset_VERIFY.json"}; + final IDataSet expectedDataSet = DataSetFactory.createDataSet(testDataSetsVerify); + + // Assert actual database table match expected table + Assertion.assertEquals(expectedDataSet, actualDataSet); + } +} diff --git a/src/test/resources/criteria/codesets.json b/src/test/resources/criteria/codesets.json new file mode 100644 index 00000000..730d38b6 --- /dev/null +++ b/src/test/resources/criteria/codesets.json @@ -0,0 +1,16 @@ +{ + "temp.codesets": [ + { + "codeset_id": 1, + "concept_id": 1 + }, + { + "codeset_id": 2, + "concept_id": 2 + }, + { + "codeset_id": 3, + "concept_id": 3 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/conditionEraDateOffset_PREP.json b/src/test/resources/criteria/conditionEraDateOffset_PREP.json new file mode 100644 index 00000000..8111927a --- /dev/null +++ b/src/test/resources/criteria/conditionEraDateOffset_PREP.json @@ -0,0 +1,71 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.condition_era": [ + { + "condition_era_id": 1, + "person_id":1, + "condition_concept_id":1, + "condition_era_start_date":"2000-01-01", + "condition_era_end_date":"2000-01-01" + }, + { + "condition_era_id": 2, + "person_id":1, + "condition_concept_id":1, + "condition_era_start_date":"2000-06-01", + "condition_era_end_date":"2000-07-01" + }, + { + "condition_era_id": 3, + "person_id":1, + "condition_concept_id":1, + "condition_era_start_date":"2000-12-31", + "condition_era_end_date":"2000-12-31" + }, + { + "condition_era_id": 4, + "person_id":2, + "condition_concept_id":1, + "condition_era_start_date":"2000-01-01", + "condition_era_end_date":"2000-01-01" + }, + { + "condition_era_id": 5, + "person_id":2, + "condition_concept_id":1, + "condition_era_start_date":"2000-12-31", + "condition_era_end_date":"2000-12-31" + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/conditionEraDateOffset_VERIFY.json b/src/test/resources/criteria/conditionEraDateOffset_VERIFY.json new file mode 100644 index 00000000..33156ee5 --- /dev/null +++ b/src/test/resources/criteria/conditionEraDateOffset_VERIFY.json @@ -0,0 +1,54 @@ +{ + "conditionEra.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-07-01", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "conditionEra.date_adjust": [ + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-16", + "end_date": "2000-06-21", + "visit_occurrence_id": null, + "sort_date": "2000-06-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/conditionOccurrenceDateOffset_PREP.json b/src/test/resources/criteria/conditionOccurrenceDateOffset_PREP.json new file mode 100644 index 00000000..a0f1dee9 --- /dev/null +++ b/src/test/resources/criteria/conditionOccurrenceDateOffset_PREP.json @@ -0,0 +1,72 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.condition_occurrence": [ + { + "condition_occurrence_id": 1, + "person_id":1, + "condition_concept_id":1, + "condition_start_date":"2000-01-01", + "condition_type_concept_id":0 + }, + { + "condition_occurrence_id": 2, + "person_id":1, + "condition_concept_id":1, + "condition_start_date":"2000-06-01", + "condition_end_date":"2000-07-01", + "condition_type_concept_id":0 + }, + { + "condition_occurrence_id": 3, + "person_id":1, + "condition_concept_id":1, + "condition_start_date":"2000-12-31", + "condition_type_concept_id":0 + }, + { + "condition_occurrence_id": 4, + "person_id":2, + "condition_concept_id":1, + "condition_start_date":"2000-01-01", + "condition_type_concept_id":0 + }, + { + "condition_occurrence_id": 5, + "person_id":2, + "condition_concept_id":1, + "condition_start_date":"2000-12-31", + "condition_type_concept_id":0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/conditionOccurrenceDateOffset_VERIFY.json b/src/test/resources/criteria/conditionOccurrenceDateOffset_VERIFY.json new file mode 100644 index 00000000..1c7c621c --- /dev/null +++ b/src/test/resources/criteria/conditionOccurrenceDateOffset_VERIFY.json @@ -0,0 +1,54 @@ +{ + "conditionOccurrence.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-07-01", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "conditionOccurrence.date_adjust": [ + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-16", + "end_date": "2000-06-21", + "visit_occurrence_id": null, + "sort_date": "2000-06-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/deathDateOffset_PREP.json b/src/test/resources/criteria/deathDateOffset_PREP.json new file mode 100644 index 00000000..4b15f0ba --- /dev/null +++ b/src/test/resources/criteria/deathDateOffset_PREP.json @@ -0,0 +1,87 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.death": [ + { + "person_id":1, + "cause_concept_id":1, + "death_date":"2000-01-01", + "death_type_concept_id":0 + }, + { + "person_id":2, + "cause_concept_id":1, + "death_date":"2000-06-01", + "death_type_concept_id":0 + }, + { + "person_id":3, + "cause_concept_id":1, + "death_date":"2000-12-31", + "death_type_concept_id": 0 + }, + { + "person_id":4, + "cause_concept_id":1, + "death_date":"2000-01-01", + "death_type_concept_id": 0 + }, + { + "person_id":5, + "cause_concept_id":1, + "death_date":"2000-12-31", + "death_type_concept_id": 0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 3, + "person_id":3, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 4, + "person_id":4, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 5, + "person_id":5, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/deathDateOffset_VERIFY.json b/src/test/resources/criteria/deathDateOffset_VERIFY.json new file mode 100644 index 00000000..e5b67413 --- /dev/null +++ b/src/test/resources/criteria/deathDateOffset_VERIFY.json @@ -0,0 +1,45 @@ +{ + "death.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-06-02", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 3, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 4, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 5, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "death.date_adjust": [] +} \ No newline at end of file diff --git a/src/test/resources/criteria/deviceExposureDateOffset_PREP.json b/src/test/resources/criteria/deviceExposureDateOffset_PREP.json new file mode 100644 index 00000000..2024a1d6 --- /dev/null +++ b/src/test/resources/criteria/deviceExposureDateOffset_PREP.json @@ -0,0 +1,72 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.device_exposure": [ + { + "device_exposure_id": 1, + "person_id":1, + "device_concept_id":1, + "device_exposure_start_date":"2000-01-01", + "device_type_concept_id":0 + }, + { + "device_exposure_id": 2, + "person_id":1, + "device_concept_id":1, + "device_exposure_start_date":"2000-06-01", + "device_exposure_end_date":"2000-07-01", + "device_type_concept_id":0 + }, + { + "device_exposure_id": 3, + "person_id":1, + "device_concept_id":1, + "device_exposure_start_date":"2000-12-31", + "device_type_concept_id":0 + }, + { + "device_exposure_id": 4, + "person_id":2, + "device_concept_id":1, + "device_exposure_start_date":"2000-01-01", + "device_type_concept_id":0 + }, + { + "device_exposure_id": 5, + "person_id":2, + "device_concept_id":1, + "device_exposure_start_date":"2000-12-31", + "device_type_concept_id":0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/deviceExposureDateOffset_VERIFY.json b/src/test/resources/criteria/deviceExposureDateOffset_VERIFY.json new file mode 100644 index 00000000..8a376ee0 --- /dev/null +++ b/src/test/resources/criteria/deviceExposureDateOffset_VERIFY.json @@ -0,0 +1,54 @@ +{ + "deviceExposure.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-07-01", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "deviceExposure.date_adjust": [ + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-16", + "end_date": "2000-06-21", + "visit_occurrence_id": null, + "sort_date": "2000-06-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/doseEraDateOffset_PREP.json b/src/test/resources/criteria/doseEraDateOffset_PREP.json new file mode 100644 index 00000000..393cda1c --- /dev/null +++ b/src/test/resources/criteria/doseEraDateOffset_PREP.json @@ -0,0 +1,81 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.dose_era": [ + { + "dose_era_id": 1, + "person_id":1, + "drug_concept_id":1, + "unit_concept_id": 0, + "dose_value": 0.0, + "dose_era_start_date":"2000-01-01", + "dose_era_end_date":"2000-01-01" + }, + { + "dose_era_id": 2, + "person_id":1, + "drug_concept_id":1, + "unit_concept_id": 0, + "dose_value": 0.0, + "dose_era_start_date":"2000-06-01", + "dose_era_end_date":"2000-07-01" + }, + { + "dose_era_id": 3, + "person_id":1, + "drug_concept_id":1, + "unit_concept_id": 0, + "dose_value": 0.0, + "dose_era_start_date":"2000-12-31", + "dose_era_end_date":"2000-12-31" + }, + { + "dose_era_id": 4, + "person_id":2, + "drug_concept_id":1, + "unit_concept_id": 0, + "dose_value": 0.0, + "dose_era_start_date":"2000-01-01", + "dose_era_end_date":"2000-01-01" + }, + { + "dose_era_id": 5, + "person_id":2, + "drug_concept_id":1, + "unit_concept_id": 0, + "dose_value": 0.0, + "dose_era_start_date":"2000-12-31", + "dose_era_end_date":"2000-12-31" + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/doseEraDateOffset_VERIFY.json b/src/test/resources/criteria/doseEraDateOffset_VERIFY.json new file mode 100644 index 00000000..a85afd26 --- /dev/null +++ b/src/test/resources/criteria/doseEraDateOffset_VERIFY.json @@ -0,0 +1,54 @@ +{ + "doseEra.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-07-01", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "doseEra.date_adjust": [ + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-16", + "end_date": "2000-06-21", + "visit_occurrence_id": null, + "sort_date": "2000-06-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/drugEraDateOffset_PREP.json b/src/test/resources/criteria/drugEraDateOffset_PREP.json new file mode 100644 index 00000000..da112473 --- /dev/null +++ b/src/test/resources/criteria/drugEraDateOffset_PREP.json @@ -0,0 +1,71 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.drug_era": [ + { + "drug_era_id": 1, + "person_id":1, + "drug_concept_id":1, + "drug_era_start_date":"2000-01-01", + "drug_era_end_date":"2000-01-01" + }, + { + "drug_era_id": 2, + "person_id":1, + "drug_concept_id":1, + "drug_era_start_date":"2000-06-01", + "drug_era_end_date":"2000-07-01" + }, + { + "drug_era_id": 3, + "person_id":1, + "drug_concept_id":1, + "drug_era_start_date":"2000-12-31", + "drug_era_end_date":"2000-12-31" + }, + { + "drug_era_id": 4, + "person_id":2, + "drug_concept_id":1, + "drug_era_start_date":"2000-01-01", + "drug_era_end_date":"2000-01-01" + }, + { + "drug_era_id": 5, + "person_id":2, + "drug_concept_id":1, + "drug_era_start_date":"2000-12-31", + "drug_era_end_date":"2000-12-31" + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/drugEraDateOffset_VERIFY.json b/src/test/resources/criteria/drugEraDateOffset_VERIFY.json new file mode 100644 index 00000000..a978eb54 --- /dev/null +++ b/src/test/resources/criteria/drugEraDateOffset_VERIFY.json @@ -0,0 +1,54 @@ +{ + "drugEra.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-07-01", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "drugEra.date_adjust": [ + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-16", + "end_date": "2000-06-21", + "visit_occurrence_id": null, + "sort_date": "2000-06-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/drugExposureDateOffset_PREP.json b/src/test/resources/criteria/drugExposureDateOffset_PREP.json new file mode 100644 index 00000000..c0fe7500 --- /dev/null +++ b/src/test/resources/criteria/drugExposureDateOffset_PREP.json @@ -0,0 +1,72 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.drug_exposure": [ + { + "drug_exposure_id": 1, + "person_id":1, + "drug_concept_id":1, + "drug_exposure_start_date":"2000-01-01", + "drug_type_concept_id":0 + }, + { + "drug_exposure_id": 2, + "person_id":1, + "drug_concept_id":1, + "drug_exposure_start_date":"2000-06-01", + "drug_exposure_end_date":"2000-07-01", + "drug_type_concept_id":0 + }, + { + "drug_exposure_id": 3, + "person_id":1, + "drug_concept_id":1, + "drug_exposure_start_date":"2000-12-31", + "drug_type_concept_id":0 + }, + { + "drug_exposure_id": 4, + "person_id":2, + "drug_concept_id":1, + "drug_exposure_start_date":"2000-01-01", + "drug_type_concept_id":0 + }, + { + "drug_exposure_id": 5, + "person_id":2, + "drug_concept_id":1, + "drug_exposure_start_date":"2000-12-31", + "drug_type_concept_id":0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/drugExposureDateOffset_VERIFY.json b/src/test/resources/criteria/drugExposureDateOffset_VERIFY.json new file mode 100644 index 00000000..d2b67e1c --- /dev/null +++ b/src/test/resources/criteria/drugExposureDateOffset_VERIFY.json @@ -0,0 +1,54 @@ +{ + "drugExposure.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-07-01", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "drugExposure.date_adjust": [ + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-16", + "end_date": "2000-06-21", + "visit_occurrence_id": null, + "sort_date": "2000-06-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/measurementDateOffset_PREP.json b/src/test/resources/criteria/measurementDateOffset_PREP.json new file mode 100644 index 00000000..dfb32ca6 --- /dev/null +++ b/src/test/resources/criteria/measurementDateOffset_PREP.json @@ -0,0 +1,71 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.measurement": [ + { + "measurement_id": 1, + "person_id":1, + "measurement_concept_id":1, + "measurement_date":"2000-01-01", + "measurement_type_concept_id":0 + }, + { + "measurement_id": 2, + "person_id":1, + "measurement_concept_id":1, + "measurement_date":"2000-06-01", + "measurement_type_concept_id":0 + }, + { + "measurement_id": 3, + "person_id":1, + "measurement_concept_id":1, + "measurement_date":"2000-12-31", + "measurement_type_concept_id":0 + }, + { + "measurement_id": 4, + "person_id":2, + "measurement_concept_id":1, + "measurement_date":"2000-01-01", + "measurement_type_concept_id":0 + }, + { + "measurement_id": 5, + "person_id":2, + "measurement_concept_id":1, + "measurement_date":"2000-12-31", + "measurement_type_concept_id":0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/measurementDateOffset_VERIFY.json b/src/test/resources/criteria/measurementDateOffset_VERIFY.json new file mode 100644 index 00000000..a74094ef --- /dev/null +++ b/src/test/resources/criteria/measurementDateOffset_VERIFY.json @@ -0,0 +1,45 @@ +{ + "measurement.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-06-02", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "measurement.date_adjust": [] +} \ No newline at end of file diff --git a/src/test/resources/criteria/observationDateOffset_PREP.json b/src/test/resources/criteria/observationDateOffset_PREP.json new file mode 100644 index 00000000..3209a36b --- /dev/null +++ b/src/test/resources/criteria/observationDateOffset_PREP.json @@ -0,0 +1,71 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.observation": [ + { + "observation_id": 1, + "person_id":1, + "observation_concept_id":1, + "observation_date":"2000-01-01", + "observation_type_concept_id":0 + }, + { + "observation_id": 2, + "person_id":1, + "observation_concept_id":1, + "observation_date":"2000-06-01", + "observation_type_concept_id":0 + }, + { + "observation_id": 3, + "person_id":1, + "observation_concept_id":1, + "observation_date":"2000-12-31", + "observation_type_concept_id":0 + }, + { + "observation_id": 4, + "person_id":2, + "observation_concept_id":1, + "observation_date":"2000-01-01", + "observation_type_concept_id":0 + }, + { + "observation_id": 5, + "person_id":2, + "observation_concept_id":1, + "observation_date":"2000-12-31", + "observation_type_concept_id":0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/observationDateOffset_VERIFY.json b/src/test/resources/criteria/observationDateOffset_VERIFY.json new file mode 100644 index 00000000..af8ecceb --- /dev/null +++ b/src/test/resources/criteria/observationDateOffset_VERIFY.json @@ -0,0 +1,45 @@ +{ + "observation.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-06-02", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "observation.date_adjust": [] +} \ No newline at end of file diff --git a/src/test/resources/criteria/observationPeriodDateOffset_PREP.json b/src/test/resources/criteria/observationPeriodDateOffset_PREP.json new file mode 100644 index 00000000..7df150eb --- /dev/null +++ b/src/test/resources/criteria/observationPeriodDateOffset_PREP.json @@ -0,0 +1,48 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.observation_period": [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2000-05-31", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":1, + "observation_period_start_date":"2000-06-01", + "observation_period_end_date":"2000-06-10", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 3, + "person_id":1, + "observation_period_start_date":"2000-07-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 4, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-12-31", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/observationPeriodDateOffset_VERIFY.json b/src/test/resources/criteria/observationPeriodDateOffset_VERIFY.json new file mode 100644 index 00000000..6c75bc57 --- /dev/null +++ b/src/test/resources/criteria/observationPeriodDateOffset_VERIFY.json @@ -0,0 +1,80 @@ +{ + "observationPeriod.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-05-31", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-06-10", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-07-01", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-07-01" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2001-12-31", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + } + ], + "observationPeriod.date_adjust": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-16", + "end_date": "2000-05-21", + "visit_occurrence_id": null, + "sort_date": "2000-01-16" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-07-16", + "end_date": "2000-12-22", + "visit_occurrence_id": null, + "sort_date": "2000-07-16" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-16", + "end_date": "2001-12-21", + "visit_occurrence_id": null, + "sort_date": "2000-01-16" + } + ], + "observationPeriod.user_defined": [ + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-09-01", + "end_date": "2000-09-30", + "visit_occurrence_id": null, + "sort_date": "2000-07-16" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-09-01", + "end_date": "2000-09-30", + "visit_occurrence_id": null, + "sort_date": "2000-01-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/payerPlanPeriodDateOffset_PREP.json b/src/test/resources/criteria/payerPlanPeriodDateOffset_PREP.json new file mode 100644 index 00000000..90caba2a --- /dev/null +++ b/src/test/resources/criteria/payerPlanPeriodDateOffset_PREP.json @@ -0,0 +1,60 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.payer_plan_period": [ + { + "payer_plan_period_id": 1, + "person_id":1, + "payer_plan_period_start_date":"2000-01-01", + "payer_plan_period_end_date":"2000-05-31" + }, + { + "payer_plan_period_id": 2, + "person_id":1, + "payer_plan_period_start_date":"2000-06-01", + "payer_plan_period_end_date":"2000-06-10" + }, + { + "payer_plan_period_id": 3, + "person_id":1, + "payer_plan_period_start_date":"2000-07-01", + "payer_plan_period_end_date":"2001-01-01" + }, + { + "payer_plan_period_id": 4, + "person_id":2, + "payer_plan_period_start_date":"2000-01-01", + "payer_plan_period_end_date":"2001-12-31" + } + ], + "cdm.observation_period": [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-12-31", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-12-31", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/payerPlanPeriodDateOffset_VERIFY.json b/src/test/resources/criteria/payerPlanPeriodDateOffset_VERIFY.json new file mode 100644 index 00000000..6f0cc363 --- /dev/null +++ b/src/test/resources/criteria/payerPlanPeriodDateOffset_VERIFY.json @@ -0,0 +1,80 @@ +{ + "payerPlanPeriod.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-05-31", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-06-10", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-07-01", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-07-01" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2001-12-31", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + } + ], + "payerPlanPeriod.date_adjust": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-16", + "end_date": "2000-05-21", + "visit_occurrence_id": null, + "sort_date": "2000-01-16" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-07-16", + "end_date": "2000-12-22", + "visit_occurrence_id": null, + "sort_date": "2000-07-16" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-16", + "end_date": "2001-12-21", + "visit_occurrence_id": null, + "sort_date": "2000-01-16" + } + ], + "payerPlanPeriod.user_defined": [ + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-09-01", + "end_date": "2000-09-30", + "visit_occurrence_id": null, + "sort_date": "2000-07-16" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-09-01", + "end_date": "2000-09-30", + "visit_occurrence_id": null, + "sort_date": "2000-01-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/procedureOccurrenceDateOffset_PREP.json b/src/test/resources/criteria/procedureOccurrenceDateOffset_PREP.json new file mode 100644 index 00000000..35ff47bd --- /dev/null +++ b/src/test/resources/criteria/procedureOccurrenceDateOffset_PREP.json @@ -0,0 +1,71 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.procedure_occurrence": [ + { + "procedure_occurrence_id": 1, + "person_id":1, + "procedure_concept_id":1, + "procedure_date":"2000-01-01", + "procedure_type_concept_id":0 + }, + { + "procedure_occurrence_id": 2, + "person_id":1, + "procedure_concept_id":1, + "procedure_date":"2000-06-01", + "procedure_type_concept_id":0 + }, + { + "procedure_occurrence_id": 3, + "person_id":1, + "procedure_concept_id":1, + "procedure_date":"2000-12-31", + "procedure_type_concept_id":0 + }, + { + "procedure_occurrence_id": 4, + "person_id":2, + "procedure_concept_id":1, + "procedure_date":"2000-01-01", + "procedure_type_concept_id":0 + }, + { + "procedure_occurrence_id": 5, + "person_id":2, + "procedure_concept_id":1, + "procedure_date":"2000-12-31", + "procedure_type_concept_id":0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/procedureOccurrenceDateOffset_VERIFY.json b/src/test/resources/criteria/procedureOccurrenceDateOffset_VERIFY.json new file mode 100644 index 00000000..a816a27c --- /dev/null +++ b/src/test/resources/criteria/procedureOccurrenceDateOffset_VERIFY.json @@ -0,0 +1,45 @@ +{ + "procedureOccurrence.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-06-02", + "visit_occurrence_id": null, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-02", + "visit_occurrence_id": null, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2001-01-01", + "visit_occurrence_id": null, + "sort_date": "2000-12-31" + } + ], + "procedureOccurrence.date_adjust": [] +} \ No newline at end of file diff --git a/src/test/resources/criteria/temp.sql b/src/test/resources/criteria/temp.sql new file mode 100644 index 00000000..e53133bc --- /dev/null +++ b/src/test/resources/criteria/temp.sql @@ -0,0 +1,4 @@ +CREATE TABLE @schemaName.codesets ( + codeset_id int NOT NULL, + concept_id bigint NOT NULL +) diff --git a/src/test/resources/criteria/visitDetailDateOffset_PREP.json b/src/test/resources/criteria/visitDetailDateOffset_PREP.json new file mode 100644 index 00000000..1bb232e1 --- /dev/null +++ b/src/test/resources/criteria/visitDetailDateOffset_PREP.json @@ -0,0 +1,81 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.visit_detail": [ + { + "visit_detail_id": 1, + "person_id":1, + "visit_detail_concept_id":1, + "visit_detail_start_date":"2000-01-01", + "visit_detail_end_date":"2000-01-01", + "visit_detail_type_concept_id": 0, + "visit_occurrence_id": 0 + }, + { + "visit_detail_id": 2, + "person_id":1, + "visit_detail_concept_id":1, + "visit_detail_start_date":"2000-06-01", + "visit_detail_end_date":"2000-07-01", + "visit_detail_type_concept_id": 0, + "visit_occurrence_id": 0 + }, + { + "visit_detail_id": 3, + "person_id":1, + "visit_detail_concept_id":1, + "visit_detail_start_date":"2000-12-31", + "visit_detail_end_date":"2000-12-31", + "visit_detail_type_concept_id": 0, + "visit_occurrence_id": 0 + }, + { + "visit_detail_id": 4, + "person_id":2, + "visit_detail_concept_id":1, + "visit_detail_start_date":"2000-01-01", + "visit_detail_end_date":"2000-01-01", + "visit_detail_type_concept_id": 0, + "visit_occurrence_id": 0 + }, + { + "visit_detail_id": 5, + "person_id":2, + "visit_detail_concept_id":1, + "visit_detail_start_date":"2000-12-31", + "visit_detail_end_date":"2000-12-31", + "visit_detail_type_concept_id": 0, + "visit_occurrence_id": 0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/visitDetailDateOffset_VERIFY.json b/src/test/resources/criteria/visitDetailDateOffset_VERIFY.json new file mode 100644 index 00000000..1e9d0fca --- /dev/null +++ b/src/test/resources/criteria/visitDetailDateOffset_VERIFY.json @@ -0,0 +1,54 @@ +{ + "visitDetail.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": 0, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-07-01", + "visit_occurrence_id": 0, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": 0, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": 0, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": 0, + "sort_date": "2000-12-31" + } + ], + "visitDetail.date_adjust": [ + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-16", + "end_date": "2000-06-21", + "visit_occurrence_id": 0, + "sort_date": "2000-06-16" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/visitOccurrenceDateOffset_PREP.json b/src/test/resources/criteria/visitOccurrenceDateOffset_PREP.json new file mode 100644 index 00000000..2e4ce4cd --- /dev/null +++ b/src/test/resources/criteria/visitOccurrenceDateOffset_PREP.json @@ -0,0 +1,76 @@ +{ + "cdm.person": [ + { + "person_id":1, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + }, + { + "person_id":2, + "gender_concept_id":0, + "year_of_birth":0, + "race_concept_id":0, + "ethnicity_concept_id":0 + } + ], + "cdm.visit_occurrence": [ + { + "visit_occurrence_id": 1, + "person_id":1, + "visit_concept_id":1, + "visit_start_date":"2000-01-01", + "visit_end_date":"2000-01-01", + "visit_type_concept_id": 0 + }, + { + "visit_occurrence_id": 2, + "person_id":1, + "visit_concept_id":1, + "visit_start_date":"2000-06-01", + "visit_end_date":"2000-07-01", + "visit_type_concept_id": 0 + }, + { + "visit_occurrence_id": 3, + "person_id":1, + "visit_concept_id":1, + "visit_start_date":"2000-12-31", + "visit_end_date":"2000-12-31", + "visit_type_concept_id": 0 + }, + { + "visit_occurrence_id": 4, + "person_id":2, + "visit_concept_id":1, + "visit_start_date":"2000-01-01", + "visit_end_date":"2000-01-01", + "visit_type_concept_id": 0 + }, + { + "visit_occurrence_id": 5, + "person_id":2, + "visit_concept_id":1, + "visit_start_date":"2000-12-31", + "visit_end_date":"2000-12-31", + "visit_type_concept_id": 0 + } + ], + "cdm.observation_period" : [ + { + "observation_period_id": 1, + "person_id":1, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + }, + { + "observation_period_id": 2, + "person_id":2, + "observation_period_start_date":"2000-01-01", + "observation_period_end_date":"2001-01-01", + "period_type_concept_id": 0 + } + ] +} \ No newline at end of file diff --git a/src/test/resources/criteria/visitOccurrenceDateOffset_VERIFY.json b/src/test/resources/criteria/visitOccurrenceDateOffset_VERIFY.json new file mode 100644 index 00000000..35bf455d --- /dev/null +++ b/src/test/resources/criteria/visitOccurrenceDateOffset_VERIFY.json @@ -0,0 +1,54 @@ +{ + "visitOccurrence.simple": [ + { + "person_id": 1, + "event_id": 1, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": 1, + "sort_date": "2000-01-01" + }, + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-01", + "end_date": "2000-07-01", + "visit_occurrence_id": 2, + "sort_date": "2000-06-01" + }, + { + "person_id": 1, + "event_id": 3, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": 3, + "sort_date": "2000-12-31" + }, + { + "person_id": 2, + "event_id": 4, + "start_date": "2000-01-01", + "end_date": "2000-01-01", + "visit_occurrence_id": 4, + "sort_date": "2000-01-01" + }, + { + "person_id": 2, + "event_id": 5, + "start_date": "2000-12-31", + "end_date": "2000-12-31", + "visit_occurrence_id": 5, + "sort_date": "2000-12-31" + } + ], + "visitOccurrence.date_adjust": [ + { + "person_id": 1, + "event_id": 2, + "start_date": "2000-06-16", + "end_date": "2000-06-21", + "visit_occurrence_id": 2, + "sort_date": "2000-06-16" + } + ] +} \ No newline at end of file