fix(oracledb): correct timestamp processing and add TimeStampLTZ support

This commit is contained in:
zgq
2024-07-07 08:40:31 +08:00
parent 9d28110135
commit 44a0e6feb5
5 changed files with 93 additions and 20 deletions

View File

@ -28,7 +28,7 @@ public class OracleValueProcessorFactory {
Map.entry(OracleColumnTypeEnum.DATE.name(), new OracleDateProcessor()),
//timestamp
Map.entry(OracleColumnTypeEnum.TIMESTAMP.name(), oracleTimeStampProcessor),
Map.entry(OracleColumnTypeEnum.TIMESTAMP_WITH_LOCAL_TIME_ZONE.getColumnType().getTypeName(), oracleTimeStampProcessor),
Map.entry(OracleColumnTypeEnum.TIMESTAMP_WITH_LOCAL_TIME_ZONE.getColumnType().getTypeName(), new OracleTimeStampLTZProcessor()),
Map.entry(OracleColumnTypeEnum.TIMESTAMP_WITH_TIME_ZONE.getColumnType().getTypeName(), new OracleTimeStampTZProcessor()),
//INTERVAL
Map.entry("INTERVALDS", new OracleIntervalDSProcessor()),

View File

@ -5,10 +5,6 @@ import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import ai.chat2db.spi.model.JDBCDataValue;
import ai.chat2db.spi.model.SQLDataValue;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author: zgq
* @date: 2024年06月04日 16:33
@ -30,20 +26,13 @@ public class OracleDateProcessor extends DefaultValueProcessor {
*/
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
Timestamp timestamp = dataValue.getTimestamp();
LocalDateTime localDateTime = timestamp.toLocalDateTime();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = localDateTime.format(formatter);
if (formattedDateTime.endsWith("00:00:00")) {
formattedDateTime = formattedDateTime.substring(0, formattedDateTime.length() - 9);
}
return formattedDateTime;
return dataValue.getStringValue();
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return OracleDmlValueTemplate.wrapDate(convertJDBCValueByType(dataValue));
return OracleDmlValueTemplate.wrapDate(dataValue.getStringValue());
}
}

View File

@ -0,0 +1,69 @@
package ai.chat2db.plugin.oracle.value.sub;
import ai.chat2db.plugin.oracle.value.template.OracleDmlValueTemplate;
import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import ai.chat2db.spi.model.JDBCDataValue;
import ai.chat2db.spi.model.SQLDataValue;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author: zgq
* @date: 2024年07月05日 下午4:19
*/
public class OracleTimeStampLTZProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return wrap(dataValue.getValue(), dataValue.getScale());
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
Timestamp timestamp = dataValue.getTimestamp();
int scale = dataValue.getScale();
LocalDateTime localDateTime = timestamp.toLocalDateTime();
StringBuilder templateBuilder = new StringBuilder("yyyy-MM-dd HH:mm:ss");
if (scale != 0) {
templateBuilder.append(".");
templateBuilder.append("S".repeat(scale));
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(templateBuilder.toString());
return localDateTime.format(formatter);
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
Timestamp timestamp = dataValue.getTimestamp();
int scale = dataValue.getScale();
// 将 Timestamp 转换为 Instant 对象
Instant instant = timestamp.toInstant();
// 将 Instant 转换为 UTC 时区的 ZonedDateTime
ZonedDateTime utcZonedDateTime = instant.atZone(ZoneId.of("UTC"));
StringBuilder templateBuilder = new StringBuilder("yyyy-MM-dd HH:mm:ss");
if (scale != 0) {
templateBuilder.append(".");
templateBuilder.append("S".repeat(scale));
}
// 定义日期时间格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(templateBuilder.toString());
// 格式化 UTC 时区的 ZonedDateTime
String formattedUtcTime = utcZonedDateTime.format(formatter);
return wrap(formattedUtcTime, scale);
}
private String wrap(String value, int scale) {
if (scale == 0) {
return OracleDmlValueTemplate.wrapDate(value);
}
return OracleDmlValueTemplate.wrapTimestamp(value, scale);
}
}

View File

@ -21,13 +21,28 @@ public class OracleTimeStampTZProcessor extends DefaultValueProcessor {
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
return dataValue.getStringValue();
//2024-06-05 17:41:27.52 +0:00 ->
String timeStampString = dataValue.getStringValue();
int scale = dataValue.getScale();
int lastSpaceIndex = timeStampString.lastIndexOf(" ");
int nanosLength = lastSpaceIndex - timeStampString.indexOf(".") - 1;
if (scale != 0 && nanosLength < scale) {
// 计算需要补充的零的数量
int zerosToAdd = scale - nanosLength;
StringBuilder sb = new StringBuilder(timeStampString);
for (int i = 0; i < zerosToAdd; i++) {
sb.insert(lastSpaceIndex, '0');
}
return sb.toString();
}
return timeStampString;
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return wrap(dataValue.getStringValue(), dataValue.getScale());
return wrap(convertJDBCValueByType(dataValue), dataValue.getScale());
}
private String wrap(String value, int scale) {

View File

@ -6,12 +6,12 @@ package ai.chat2db.plugin.oracle.value.template;
*/
public class OracleDmlValueTemplate {
public static final String DATE_TEMPLATE = "TO_DATE('%s', 'YYYY-MM-DD HH24:MI:SS')";
public static final String DATE_TEMPLATE = "TO_DATE('%s', 'SYYYY-MM-DD HH24:MI:SS')";
public static final String TIMESTAMP_TEMPLATE = "TO_TIMESTAMP('%s', 'YYYY-MM-DD HH24:MI:SS.FF%d')";
public static final String TIMESTAMP_TEMPLATE = "TO_TIMESTAMP('%s', 'SYYYY-MM-DD HH24:MI:SS.FF%d')";
public static final String TIMESTAMP_TZ_TEMPLATE = "TO_TIMESTAMP_TZ('%s', 'YYYY-MM-DD HH24:MI:SS.FF%d TZH:TZM')";
public static final String TIMESTAMP_TZ_WITHOUT_NANOS_TEMPLATE = "TO_TIMESTAMP_TZ('%s', 'YYYY-MM-DD HH24:MI:SS TZH:TZM')";
public static final String TIMESTAMP_TZ_TEMPLATE = "TO_TIMESTAMP_TZ('%s', 'SYYYY-MM-DD HH24:MI:SS.FF%d TZR')";
public static final String TIMESTAMP_TZ_WITHOUT_NANOS_TEMPLATE = "TO_TIMESTAMP_TZ('%s', 'SYYYY-MM-DD HH24:MI:SS TZR')";
public static final String INTERVAL_YEAR_TO_MONTH_TEMPLATE = "INTERVAL '%s' YEAR(%d) TO MONTH";
public static final String INTERVAL_DAY_TO_SECOND_TEMPLATE = "INTERVAL '%s' DAY(%d) TO SECOND(%d)";