Skip to content

Commit

Permalink
Improve the SQL Server plugin to include milliseconds when saving NST…
Browse files Browse the repository at this point in the history
…imestamp values
  • Loading branch information
hprange committed Jul 25, 2022
1 parent a859052 commit 043298c
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.webobjects.jdbcadaptor;

import com.webobjects.eoaccess.EOAttribute;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.foundation.NSMutableDictionary;
import com.webobjects.foundation.NSTimestamp;
import com.webobjects.foundation.NSTimestampFormatter;

import java.sql.Timestamp;

/**
* Overrides {@code MicrosoftExpression} in order to add TIMESTAMP values including milliseconds.
*
* @author hprange (most code was copied from {@code EROracleExpression})
*/
public class ERMicrosoftExpression extends MicrosoftPlugIn.MicrosoftExpression {
private static final NSTimestampFormatter _TIMESTAMP_FORMATTER = new NSTimestampFormatter("%Y-%m-%d %H:%M:%S.%F");

public ERMicrosoftExpression(EOEntity entity) {
super(entity);
}

/**
* Overridden in order to add milliseconds to the value. This applies only if value is an instance of
* {@code NSTimestamp} and if valueType from the attribute is {@code 'T'}.
*
* @param attribute the EOAttribute associated with the bind variable dictionary
* @param value the value associated with the bind variable dictionary
* @return the modified bind variable dictionary for {@code attribute} and {@code value}
*/
@Override
public NSMutableDictionary<String, Object> bindVariableDictionaryForAttribute(EOAttribute attribute, Object value) {
NSMutableDictionary<String, Object> result = super.bindVariableDictionaryForAttribute(attribute, value);

if (value instanceof NSTimestamp && isTimestampAttribute(attribute)) {
NSTimestamp nstimestamp = (NSTimestamp) value;
long millis = nstimestamp.getTime();
// AK: since NSTimestamp places fractional millis in the getTime,
// the driver is getting very confused and refuses to update the columns as
// they get translated to 0 as the fractional values.
Timestamp timestamp = new Timestamp(millis);
timestamp.setNanos(timestamp.getNanos() + nstimestamp.getNanos());
result.setObjectForKey(timestamp, "BindVariableValue");
}

return result;
}

/**
* Overridden to add milliseconds to the value. This applies only if value is an instance of {@code NSTimestamp} and
* if valueType from the attribute is {@code T}.
*
* @param value an object to be used in a SQL statement
* @param attribute an EOAttribute to be used in influencing the format
* @return the modified formatted string
*/
@Override
public String formatValueForAttribute(Object value, EOAttribute attribute) {
if (value instanceof NSTimestamp && isTimestampAttribute(attribute)) {
return "'" + _TIMESTAMP_FORMATTER.format(value) + "'";
}

return super.formatValueForAttribute(value, attribute);
}

private boolean isTimestampAttribute(EOAttribute attribute) {
return "T".equals(attribute.valueType());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ public String defaultDriverName() {
return "com.microsoft.sqlserver.jdbc.SQLServerDriver";
}

/**
* Uses the enhanced {@code ERMicrosoftExpression} as the expression class.
*/
@Override
public Class defaultExpressionClass() {
return ERMicrosoftExpression.class;
}

/**
* Generates a batch of new primary keys for the given entity. Overrides the default implementation to provide a
* more efficient mechanism for generating primary keys using database sequences.
Expand Down

0 comments on commit 043298c

Please sign in to comment.