OracleValueProcessor

This commit is contained in:
zgq
2024-06-05 20:17:33 +08:00
parent de9c187a68
commit f0b90cab0d
21 changed files with 638 additions and 74 deletions

View File

@ -11,8 +11,10 @@ import ai.chat2db.plugin.oracle.builder.OracleSqlBuilder;
import ai.chat2db.plugin.oracle.type.OracleColumnTypeEnum;
import ai.chat2db.plugin.oracle.type.OracleDefaultValueEnum;
import ai.chat2db.plugin.oracle.type.OracleIndexTypeEnum;
import ai.chat2db.plugin.oracle.value.OracleValueProcessor;
import ai.chat2db.spi.MetaData;
import ai.chat2db.spi.SqlBuilder;
import ai.chat2db.spi.ValueProcessor;
import ai.chat2db.spi.jdbc.DefaultMetaService;
import ai.chat2db.spi.model.*;
import ai.chat2db.spi.sql.SQLExecutor;
@ -340,4 +342,12 @@ public class OracleMetaData extends DefaultMetaService implements MetaData {
public List<String> getSystemSchemas() {
return systemSchemas;
}
/**
* @return
*/
@Override
public ValueProcessor getValueProcessor() {
return new OracleValueProcessor();
}
}

View File

@ -1,5 +1,6 @@
package ai.chat2db.plugin.oracle.value;
import ai.chat2db.plugin.oracle.value.factory.OracleValueProcessorFactory;
import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import ai.chat2db.spi.model.JDBCDataValue;
import ai.chat2db.spi.model.SQLDataValue;
@ -13,18 +14,19 @@ public class OracleValueProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return super.convertSQLValueByType(dataValue);
return OracleValueProcessorFactory.getValueProcessor(dataValue.getDateTypeName()).convertSQLValueByType(dataValue);
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
return super.convertJDBCValueByType(dataValue);
String type = dataValue.getType();
return OracleValueProcessorFactory.getValueProcessor(dataValue.getType()).convertJDBCValueByType(dataValue);
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return super.convertJDBCValueStrByType(dataValue);
return OracleValueProcessorFactory.getValueProcessor(dataValue.getType()).convertJDBCValueStrByType(dataValue);
}
}

View File

@ -1,9 +1,47 @@
package ai.chat2db.plugin.oracle.value.factory;
import ai.chat2db.plugin.oracle.type.OracleColumnTypeEnum;
import ai.chat2db.plugin.oracle.value.sub.*;
import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import java.util.Map;
/**
* @author: zgq
* @date: 2024年06月03日 23:21
*/
*/ // TODO: 1.空间数据类型 2.XML数据类型 3.动态类型数据 4.ANSI、DB2 和 SQL/DS 数据
public class OracleValueProcessorFactory {
private static final Map<String, DefaultValueProcessor> PROCESSOR_MAP;
static {
OracleClobProcessor oracleClobProcessor = new OracleClobProcessor();
OracleTimeStampProcessor oracleTimeStampProcessor = new OracleTimeStampProcessor();
PROCESSOR_MAP = Map.ofEntries(
//clob
Map.entry(OracleColumnTypeEnum.CLOB.name(), oracleClobProcessor),
Map.entry(OracleColumnTypeEnum.NCLOB.name(), oracleClobProcessor),
Map.entry(OracleColumnTypeEnum.LONG.name(), oracleClobProcessor),
//date
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_TIME_ZONE.getColumnType().getTypeName(), new OracleTimeStampTZProcessor()),
//INTERVAL
Map.entry("INTERVALDS", new OracleIntervalDSProcessor()),
Map.entry("INTERVALYM", new OracleIntervalYMProcessor()),
//number
Map.entry(OracleColumnTypeEnum.NUMBER.name(), new OracleNumberProcessor()),
//blob
Map.entry(OracleColumnTypeEnum.BLOB.name(), new OracleBlobProcessor())
);
}
public static DefaultValueProcessor getValueProcessor(String type) {
DefaultValueProcessor processor = PROCESSOR_MAP.get(type);
return processor == null ? new DefaultValueProcessor() : processor;
}
}

View File

@ -0,0 +1,38 @@
package ai.chat2db.plugin.oracle.value.sub;
import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import ai.chat2db.spi.model.JDBCDataValue;
import ai.chat2db.spi.model.SQLDataValue;
import ai.chat2db.spi.sql.Chat2DBContext;
import lombok.extern.slf4j.Slf4j;
/**
* @author: zgq
* @date: 2024年06月05日 20:06
*/
@Slf4j
public class OracleBlobProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return dataValue.getBlobHexString();
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
try {
return dataValue.getBlobString(true);
} catch (Exception e) {
log.warn("convertJDBCValueByType error database: {} , error dataType: {} ",
Chat2DBContext.getDBConfig().getDbType(), dataValue.getType(), e);
return super.convertJDBCValueByType(dataValue);
}
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return dataValue.getBlobHexString();
}
}

View File

@ -0,0 +1,34 @@
package ai.chat2db.plugin.oracle.value.sub;
import ai.chat2db.server.tools.common.util.EasyStringUtils;
import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import ai.chat2db.spi.model.JDBCDataValue;
import ai.chat2db.spi.model.SQLDataValue;
/**
* @author: zgq
* @date: 2024年06月04日 17:06
*/
public class OracleClobProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return wrap(dataValue.getValue());
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
return dataValue.getClobString(true);
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return wrap(dataValue.getClobString(false));
}
private String wrap(String value) {
return EasyStringUtils.escapeAndQuoteString(value);
}
}

View File

@ -0,0 +1,56 @@
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.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author: zgq
* @date: 2024年06月04日 16:33
*/
public class OracleDateProcessor extends DefaultValueProcessor {
/**
* @param dataValue
* @return
*/
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return wrap(dataValue.getValue());
}
/**
* @param dataValue
* @return
*/
@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;
}
/**
* @param dataValue
* @return
*/
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return wrap(convertJDBCValueByType(dataValue));
}
private String wrap(String value) {
return String.format(OracleDmlValueTemplate.DATE_TEMPLATE, value);
}
}

View File

@ -0,0 +1,35 @@
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;
/**
* @author: zgq
* @date: 2024年06月05日 18:56
*/
public class OracleIntervalDSProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return wrap(dataValue.getValue(), dataValue.getPrecision(), dataValue.getScale());
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
return super.convertJDBCValueByType(dataValue);
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return wrap(convertJDBCValueByType(dataValue), dataValue.getPrecision(), dataValue.getScale());
}
private String wrap(String value, int precision, int scale) {
return String.format(OracleDmlValueTemplate.INTEGER_DAY_TO_SECOND_TEMPLATE, value, precision, scale);
}
}

View File

@ -0,0 +1,36 @@
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;
/**
* 功能描述
*
* @author: zgq
* @date: 2024年06月05日 18:58
*/
public class OracleIntervalYMProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return wrap(dataValue.getValue(), dataValue.getPrecision());
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
return super.convertJDBCValueByType(dataValue);
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return wrap(convertJDBCValueByType(dataValue), dataValue.getPrecision());
}
public String wrap(String value, int precision) {
return String.format(OracleDmlValueTemplate.INTEGER_YEAR_TO_MONTH_TEMPLATE, value, precision);
}
}

View File

@ -0,0 +1,31 @@
package ai.chat2db.plugin.oracle.value.sub;
import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import ai.chat2db.spi.model.JDBCDataValue;
import ai.chat2db.spi.model.SQLDataValue;
/**
* 功能描述
*
* @author: zgq
* @date: 2024年06月05日 20:00
*/
public class OracleNumberProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return super.convertSQLValueByType(dataValue);
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
return dataValue.getBigDecimalString();
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return convertJDBCValueByType(dataValue);
}
}

View File

@ -0,0 +1,52 @@
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.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author: zgq
* @date: 2024年06月05日 16:20
*/
public class OracleTimeStampProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return wrap(dataValue.getValue(), dataValue.getScale());
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
// TODO: datagrip对timestampLTZ的处理是不受时区影响的但其实这个字段就是为了可以协同时区问题的有待商讨
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) {
return wrap(convertJDBCValueByType(dataValue), dataValue.getScale());
}
private String wrap(String value, int scale) {
if (scale == 0) {
return String.format(OracleDmlValueTemplate.DATE_TEMPLATE, value);
}
return String.format(OracleDmlValueTemplate.TIMESTAMP_TEMPLATE, value, scale);
}
}

View File

@ -0,0 +1,41 @@
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;
/**
* 功能描述
*
* @author: zgq
* @date: 2024年06月05日 17:32
*/
public class OracleTimeStampTZProcessor extends DefaultValueProcessor {
@Override
public String convertSQLValueByType(SQLDataValue dataValue) {
return wrap(dataValue.getValue(), dataValue.getScale());
}
@Override
public String convertJDBCValueByType(JDBCDataValue dataValue) {
// TODO: return:2024-06-05 17:32:52.849 +8:00 but it actually is 2024-06-05 17:32:52.849000 +8:00
return super.convertJDBCValueByType(dataValue);
}
@Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return wrap(convertJDBCValueByType(dataValue), dataValue.getScale());
}
private String wrap(String value, int scale) {
if (scale == 0) {
return String.format(OracleDmlValueTemplate.TIMESTAMP_TZ_WITHOUT_NANOS_TEMPLATE, value);
}
return String.format(OracleDmlValueTemplate.TIMESTAMP_TZ_TEMPLATE, value, scale);
}
}

View File

@ -6,5 +6,13 @@ package ai.chat2db.plugin.oracle.value.template;
*/
public class OracleDmlValueTemplate {
public static final String DATE_TEMPLATE = "TO_DATE('%s', 'SYYYY-MM-DD HH24:MI:SS')";
public static final String DATE_TEMPLATE = "TO_DATE('%s', 'YYYY-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_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 INTEGER_YEAR_TO_MONTH_TEMPLATE = "INTERVAL '%s' YEAR(%d) TO MONTH";
public static final String INTEGER_DAY_TO_SECOND_TEMPLATE = "INTERVAL '%s' DAY(%d) TO SECOND(%d)";
}