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