Skip to content

Commit c53bc36

Browse files
authored
Merge pull request #506 from IBM/issue-255-lastupdated
Improve Date Time support and _lastUpdated behavior #255 #258 #437
2 parents 7268d15 + 8c5a9ac commit c53bc36

47 files changed

Lines changed: 4243 additions & 1908 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

fhir-core/src/main/java/com/ibm/fhir/core/FHIRUtilities.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import java.sql.Timestamp;
1010
import java.text.SimpleDateFormat;
11+
import java.time.ZoneId;
1112
import java.util.Base64;
1213
import java.util.Date;
1314
import java.util.TimeZone;
@@ -117,7 +118,7 @@ public static boolean isEncoded(String s) {
117118
* @return
118119
*/
119120
public static Timestamp convertToTimestamp(java.time.ZonedDateTime zdt) {
120-
return new Timestamp(zdt.toInstant().toEpochMilli());
121+
return Timestamp.from(zdt.withZoneSameInstant(ZoneId.of("UTC")).toInstant());
121122
}
122123

123124

fhir-database-utils/src/main/java/com/ibm/fhir/database/utils/derby/DerbyMaster.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public class DerbyMaster implements AutoCloseable {
4646
private final String database;
4747

4848
// Controls if we run derby in debugging mode which enables more logs.
49-
private final boolean debugging = false;
49+
private static final boolean DEBUG = false;
5050

5151
/**
5252
* Public constructor
@@ -60,7 +60,7 @@ public DerbyMaster(String database) {
6060
Class.forName(DERBY_TRANSLATOR.getDriverClassName());
6161
// This speeds up sequence fetching by pre-creating 1000 instead of the default 100.
6262
out.println("derby.language.sequence.preallocator=1000");
63-
if (debugging) {
63+
if (DEBUG) {
6464
out.println("derby.language.logQueryPlan=true");
6565
out.println("derby.language.logStatementText=true");
6666
out.println("derby.locks.deadlockTrace=true");

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/JDBCConstants.java

Lines changed: 47 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
import java.util.Map;
1212

1313
import com.ibm.fhir.search.SearchConstants.Modifier;
14-
import com.ibm.fhir.search.SearchConstants.Prefix;
1514
import com.ibm.fhir.search.SearchConstants.Type;
1615

1716
public class JDBCConstants {
1817
/**
19-
* The maximum number of components allowed within a search parameter of type composite
18+
* The maximum number of components allowed within a search parameter of type
19+
* composite
2020
*/
2121
public static final int MAX_NUM_OF_COMPOSITE_COMPONENTS = 3;
22-
22+
2323
// Constants for the IBM FHIR Server database schema
2424
public static final String STR_VALUE = "STR_VALUE";
2525
public static final String STR_VALUE_LCASE = "STR_VALUE_LCASE";
@@ -35,15 +35,14 @@ public class JDBCConstants {
3535
public static final String DATE_END = "DATE_END";
3636
public static final String LATITUDE_VALUE = "LATITUDE_VALUE";
3737
public static final String LONGITUDE_VALUE = "LONGITUDE_VALUE";
38-
38+
3939
// Generic SQL query string constants
4040
public static final String DOT = ".";
41+
public static final char DOT_CHAR = '.';
4142
public static final String WHERE = " WHERE ";
4243
public static final String PARAMETER_TABLE_ALIAS = "pX";
4344
public static final String LEFT_PAREN = "(";
4445
public static final String RIGHT_PAREN = ")";
45-
public static final String AND = " AND ";
46-
public static final String OR = " OR ";
4746
public static final String BIND_VAR = "?";
4847
public static final String PERCENT_WILDCARD = "%";
4948
public static final String UNDERSCORE_WILDCARD = "_";
@@ -60,25 +59,49 @@ public class JDBCConstants {
6059
public static final String ON = " ON ";
6160
public static final String JOIN = " JOIN ";
6261
public static final String LEFT_JOIN = " LEFT JOIN ";
63-
public static final String COMBINED_RESULTS = " COMBINED_RESULTS";
62+
public static final String COMBINED_RESULTS = ") COMBINED_RESULTS";
63+
public static final String COMMA = " , ";
64+
public static final char COMMA_CHAR = ',';
65+
public static final char QUOTE = '\'';
66+
public static final char PATH_CHAR = '/';
67+
68+
// JDBC Operators
69+
public static final String EQ = " = ";
70+
public static final String LIKE = " LIKE ";
71+
public static final String IN =" IN ";
72+
public static final String LT = " < ";
73+
public static final String LTE = " <= ";
74+
public static final String GT = " > ";
75+
public static final String GTE = " >= ";
76+
public static final String NE = " <> ";
77+
public static final String OR = " OR ";
78+
public static final String AND = " AND ";
79+
80+
// ASC/DESC
81+
public static final String ORDER_BY = " ORDER BY ";
82+
public static final String ASCENDING = "ASC";
83+
public static final String DESCENDING = "DESC";
84+
85+
public static final String DEFAULT_ORDERING = " ORDER BY RESOURCE_ID ASC ";
86+
public static final String DEFAULT_ORDERING_WITH_TABLE = " ORDER BY R.RESOURCE_ID ASC ";
87+
88+
// MIN / MAX
89+
public static final String MAX = "MAX";
90+
public static final String MIN = "MIN";
6491

6592
/**
66-
* Maps search parameter types to the currently supported list of modifiers for that type.
93+
* Maps search parameter types to the currently supported list of modifiers for
94+
* that type.
6795
*/
68-
public static Map<Type, List<Modifier>> supportedModifiersMap;
96+
public static final Map<Type, List<Modifier>> supportedModifiersMap;
6997

7098
/**
7199
* Maps Parameter modifiers to SQL operators.
72100
*/
73-
public static Map<Modifier, JDBCOperator> modifierOperatorMap;
74-
75-
/**
76-
* Maps Parameter value prefix operators to SQL operators.
77-
*/
78-
public static Map<Prefix, JDBCOperator> prefixOperatorMap;
101+
public static final Map<Modifier, String> modifierOperatorMap;
79102

80103
static {
81-
supportedModifiersMap = new HashMap<Type, List<Modifier>>();
104+
supportedModifiersMap = new HashMap<>();
82105
supportedModifiersMap.put(Type.STRING, Arrays.asList(Modifier.EXACT, Modifier.CONTAINS, Modifier.MISSING));
83106
supportedModifiersMap.put(Type.REFERENCE, Arrays.asList(Modifier.TYPE, Modifier.MISSING));
84107
supportedModifiersMap.put(Type.URI, Arrays.asList(Modifier.BELOW, Modifier.ABOVE, Modifier.MISSING));
@@ -90,56 +113,14 @@ public class JDBCConstants {
90113
supportedModifiersMap.put(Type.SPECIAL, Arrays.asList(Modifier.MISSING));
91114

92115
modifierOperatorMap = new HashMap<>();
93-
modifierOperatorMap.put(Modifier.ABOVE, JDBCOperator.GT);
94-
modifierOperatorMap.put(Modifier.BELOW, JDBCOperator.LT);
95-
modifierOperatorMap.put(Modifier.CONTAINS, JDBCOperator.LIKE);
96-
modifierOperatorMap.put(Modifier.EXACT, JDBCOperator.EQ);
97-
modifierOperatorMap.put(Modifier.NOT, JDBCOperator.NE);
98-
99-
prefixOperatorMap = new HashMap<>();
100-
prefixOperatorMap.put(Prefix.EQ, JDBCOperator.EQ);
101-
prefixOperatorMap.put(Prefix.GE, JDBCOperator.GTE);
102-
prefixOperatorMap.put(Prefix.GT, JDBCOperator.GT);
103-
prefixOperatorMap.put(Prefix.LE, JDBCOperator.LTE);
104-
prefixOperatorMap.put(Prefix.LT, JDBCOperator.LT);
105-
prefixOperatorMap.put(Prefix.NE, JDBCOperator.NE);
106-
prefixOperatorMap.put(Prefix.SA, JDBCOperator.GT);
107-
prefixOperatorMap.put(Prefix.EB, JDBCOperator.LT);
108-
prefixOperatorMap.put(Prefix.AP, JDBCOperator.EQ);
116+
modifierOperatorMap.put(Modifier.ABOVE, GT);
117+
modifierOperatorMap.put(Modifier.BELOW, LT);
118+
modifierOperatorMap.put(Modifier.CONTAINS, LIKE);
119+
modifierOperatorMap.put(Modifier.EXACT, EQ);
120+
modifierOperatorMap.put(Modifier.NOT, NE);
109121
}
110122

111-
/**
112-
* An enumeration of SQL query operators.
113-
*/
114-
public static enum JDBCOperator {
115-
EQ(" = "),
116-
LIKE(" LIKE "),
117-
IN(" IN "),
118-
LT(" < "),
119-
LTE(" <= "),
120-
GT(" > "),
121-
GTE(" >= "),
122-
NE(" <> "),
123-
OR(" OR "),
124-
AND(" AND ");
125-
126-
private String value = null;
127-
128-
JDBCOperator(String value) {
129-
this.value = value;
130-
}
131-
132-
public String value() {
133-
return value;
134-
}
135-
136-
public static JDBCOperator fromValue(String value) {
137-
for (JDBCOperator operator : JDBCOperator.values()) {
138-
if (operator.value.equalsIgnoreCase(value)) {
139-
return operator;
140-
}
141-
}
142-
throw new IllegalArgumentException("No constant with value " + value + " found.");
143-
}
123+
private JDBCConstants() {
124+
// Hide the constructor
144125
}
145-
}
126+
}

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/dao/api/FHIRDbDAO.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
*/
1616
public interface FHIRDbDAO {
1717

18-
String FHIRDB_JNDI_NAME_DEFAULT = "jdbc/fhirDB";
19-
String PROPERTY_DB_DRIVER = "dbDriverName";
20-
String PROPERTY_DB_URL = "dbUrl";
21-
String PROPERTY_DB2_USER = "user";
22-
String PROPERTY_DB2_PSWD = "password";
18+
public static final String FHIRDB_JNDI_NAME_DEFAULT = "jdbc/fhirDB";
19+
public static final String PROPERTY_DB_DRIVER = "dbDriverName";
20+
public static final String PROPERTY_DB_URL = "dbUrl";
21+
public static final String PROPERTY_DB2_USER = "user";
22+
public static final String PROPERTY_DB2_PSWD = "password";
2323

2424
/**
2525
* Acquires and returns a JDBC database connection to the FHIR database.

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/dao/api/ParameterDAO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public interface ParameterDAO extends FHIRDbDAO {
9797
* @param codeSystemId The id corresponding to the code system name.
9898
* @throws FHIRPersistenceException
9999
*/
100-
void addCodeSystemsCacheCandidate(String codeSystemName, Integer codeSystemId) throws FHIRPersistenceException;
100+
void addCodeSystemsCacheCandidate(String codeSystemName, Integer codeSystemId) throws FHIRPersistenceException;
101101

102102
/**
103103
* Adds a parameter name / parameter id pair to a candidate collection for population into the ParameterNamesCache.

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/dao/api/ResourceDAO.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import com.ibm.fhir.persistence.context.FHIRPersistenceContext;
1414
import com.ibm.fhir.persistence.exception.FHIRPersistenceException;
1515
import com.ibm.fhir.persistence.exception.FHIRPersistenceVersionIdMismatchException;
16-
import com.ibm.fhir.persistence.jdbc.dto.StringParmVal;
1716
import com.ibm.fhir.persistence.jdbc.dto.ExtractedParameterValue;
1817
import com.ibm.fhir.persistence.jdbc.dto.Resource;
1918
import com.ibm.fhir.persistence.jdbc.exception.FHIRPersistenceDBConnectException;

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/dao/impl/FHIRDbDAOImpl.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public Connection getConnection() throws FHIRPersistenceDBConnectException {
140140
}
141141
else if (this.connectionProvider != null) {
142142
try {
143-
connection = connectionProvider.getConnection();
143+
connection = connectionProvider.getConnection();
144144
}
145145
catch (SQLException x) {
146146
FHIRPersistenceDBConnectException fx = new FHIRPersistenceDBConnectException("Failed to acquire database connection from provider");
@@ -361,7 +361,7 @@ protected List<Resource> runQuery(String sql, Object... searchArgs) throws FHIRP
361361
connection = this.getConnection();
362362
stmt = connection.prepareStatement(sql);
363363
// Inject arguments into the prepared stmt.
364-
for (int i = 0; i <searchArgs.length; i++) {
364+
for (int i = 0; i <searchArgs.length; i++) {
365365
stmt.setObject(i+1, searchArgs[i]);
366366
}
367367
dbCallStartTime = System.nanoTime();
@@ -404,20 +404,20 @@ protected List<Resource> runQuery(String sql, Object... searchArgs) throws FHIRP
404404
protected int runCountQuery(String sql, Object... searchArgs) throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException {
405405
final String METHODNAME = "runCountQuery";
406406
log.entering(CLASSNAME, METHODNAME);
407-
407+
408408
int rowCount = 0;
409409
Connection connection = null;
410410
PreparedStatement stmt = null;
411411
ResultSet resultSet = null;
412412
String errMsg = "Failure retrieving count. SQL=" + sql + NEWLINE + " searchArgs=" + Arrays.toString(searchArgs);
413413
long dbCallStartTime;
414414
double dbCallDuration;
415-
415+
416416
try {
417417
connection = this.getConnection();
418418
stmt = connection.prepareStatement(sql);
419419
// Inject arguments into the prepared stmt.
420-
for (int i = 0; i <searchArgs.length; i++) {
420+
for (int i = 0; i <searchArgs.length; i++) {
421421
stmt.setObject(i+1, searchArgs[i]);
422422
}
423423
dbCallStartTime = System.nanoTime();

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/dao/impl/ParameterVisitorBatchDAO.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public class ParameterVisitorBatchDAO implements ExtractedParameterValueVisitor,
7474
private final PreparedStatement quantities;
7575
private int quantityCount;
7676

77-
// rarely used so no need for PreparedStatement or batching on this one;
77+
// rarely used so no need for {@code java.sql.PreparedStatement} or batching on this one
7878
// even on Location resources its only there once by default
7979
private final String insertLocation;
8080

@@ -338,8 +338,8 @@ public void visit(DateParmVal param) throws FHIRPersistenceException {
338338
}
339339
else {
340340
if (logger.isLoggable(Level.FINE)) {
341-
logger.fine("dateValue: " + parameterName + "[" + parameterNameId + "], "
342-
+ date + " [" + dateStart + ", " + dateEnd + "]");
341+
logger.fine("dateValue: " + parameterName + "[" + parameterNameId + "], value: ["
342+
+ date + "], period: [" + dateStart + ", " + dateEnd + "]");
343343
}
344344

345345
setDateParms(dates, parameterNameId, date, dateStart, dateEnd);

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/dao/impl/ResourceDAOImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,10 +453,9 @@ public void addResourceTypeCacheCandidate(String resourceType, Integer resourceT
453453

454454
}
455455

456-
@Override
457456
public Resource insert(Resource resource, List<ExtractedParameterValue> parameters, ParameterDAO parameterDao)
458457
throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException, FHIRPersistenceVersionIdMismatchException {
459-
final String METHODNAME = "insert(Resource, List<Parameter>";
458+
final String METHODNAME = "insert(Resource, List<ExtractedParameterValue>";
460459
log.entering(CLASSNAME, METHODNAME);
461460

462461
try {
@@ -770,4 +769,4 @@ public List<String> searchStringValues(SqlQueryData queryData)
770769
log.exiting(CLASSNAME, METHODNAME);
771770
}
772771
}
773-
}
772+
}

fhir-persistence-jdbc/src/main/java/com/ibm/fhir/persistence/jdbc/derby/FhirRefSequenceDAOImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public int nextValue() throws SQLException {
3636
try (PreparedStatement stmt = conn.prepareStatement(SEQ)) {
3737
ResultSet rs = stmt.executeQuery();
3838
if (rs.next()) {
39-
result = rs.getInt(1);
39+
result = rs.getInt(1);
4040
}
4141
else {
4242
// not gonna happen

0 commit comments

Comments
 (0)