MysqlValueProcessor and OracleValueProcessor

This commit is contained in:
zgq
2024-06-12 10:57:46 +08:00
parent f0b90cab0d
commit 591188703a
10 changed files with 104 additions and 40 deletions

View File

@ -2,13 +2,11 @@ package ai.chat2db.plugin.mysql.builder;
import ai.chat2db.plugin.mysql.type.MysqlColumnTypeEnum; import ai.chat2db.plugin.mysql.type.MysqlColumnTypeEnum;
import ai.chat2db.plugin.mysql.type.MysqlIndexTypeEnum; import ai.chat2db.plugin.mysql.type.MysqlIndexTypeEnum;
import ai.chat2db.spi.SqlBuilder;
import ai.chat2db.spi.jdbc.DefaultSqlBuilder; import ai.chat2db.spi.jdbc.DefaultSqlBuilder;
import ai.chat2db.spi.model.Database; import ai.chat2db.spi.model.Database;
import ai.chat2db.spi.model.Table; import ai.chat2db.spi.model.Table;
import ai.chat2db.spi.model.TableColumn; import ai.chat2db.spi.model.TableColumn;
import ai.chat2db.spi.model.TableIndex; import ai.chat2db.spi.model.TableIndex;
import cn.hutool.core.util.ArrayUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.*; import java.util.*;
@ -288,14 +286,14 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder {
// 连续数据数量 // 连续数据数量
if (from < to) { if (from < to) {
for (int i = to; i < originalArray.length - 1; i++) { for (int i = to; i < originalArray.length - 1; i++) {
if (originalArray[i+1].equals(targetArray[findIndex(targetArray, originalArray[i]) +1])) { if (originalArray[i + 1].equals(targetArray[findIndex(targetArray, originalArray[i]) + 1])) {
continuousDataCount.set(continuousDataCount.incrementAndGet()); continuousDataCount.set(continuousDataCount.incrementAndGet());
} else { } else {
break; break;
} }
} }
if (continuousDataCount.get() > 0) { if (continuousDataCount.get() > 0) {
System.arraycopy(originalArray, from + 1, newArray, from, to - from +1); System.arraycopy(originalArray, from + 1, newArray, from, to - from + 1);
isContinuousData = true; isContinuousData = true;
} else { } else {
System.arraycopy(originalArray, from + 1, newArray, from, to - from); System.arraycopy(originalArray, from + 1, newArray, from, to - from);
@ -303,12 +301,20 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder {
} else { } else {
System.arraycopy(originalArray, to, newArray, to + 1, from - to); System.arraycopy(originalArray, to, newArray, to + 1, from - to);
} }
if (isContinuousData){ if (isContinuousData) {
newArray[to+continuousDataCount.get()] = temp; newArray[to + continuousDataCount.get()] = temp;
} else { } else {
newArray[to] = temp; newArray[to] = temp;
} }
return newArray; return newArray;
} }
@Override
protected void buildTableName(String databaseName, String schemaName, String tableName, StringBuilder script) {
if (StringUtils.isNotBlank(databaseName)) {
script.append("`").append(databaseName).append("`").append('.');
}
script.append("`").append(tableName).append("`");
}
} }

View File

@ -27,11 +27,13 @@ public class MysqlValueProcessor extends DefaultValueProcessor {
@Override @Override
public String convertJDBCValueByType(JDBCDataValue dataValue) { public String convertJDBCValueByType(JDBCDataValue dataValue) {
return MysqlValueProcessorFactory.getValueProcessor(dataValue.getType()).convertJDBCValueByType(dataValue); String type = dataValue.getType();
return MysqlValueProcessorFactory.getValueProcessor(type).convertJDBCValueByType(dataValue);
} }
@Override @Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) { public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return MysqlValueProcessorFactory.getValueProcessor(dataValue.getType()).convertJDBCValueStrByType(dataValue); String type = dataValue.getType();
return MysqlValueProcessorFactory.getValueProcessor(type).convertJDBCValueStrByType(dataValue);
} }
} }

View File

@ -35,6 +35,7 @@ public class MysqlValueProcessorFactory {
Map.entry(MysqlColumnTypeEnum.MULTIPOLYGON.name(), mysqlGeometryProcessor), Map.entry(MysqlColumnTypeEnum.MULTIPOLYGON.name(), mysqlGeometryProcessor),
Map.entry(MysqlColumnTypeEnum.GEOMETRYCOLLECTION.name(), mysqlGeometryProcessor), Map.entry(MysqlColumnTypeEnum.GEOMETRYCOLLECTION.name(), mysqlGeometryProcessor),
// binary // binary
Map.entry(MysqlColumnTypeEnum.VARBINARY.name(), mysqlVarBinaryProcessor),
Map.entry(MysqlColumnTypeEnum.BLOB.name(), mysqlVarBinaryProcessor), Map.entry(MysqlColumnTypeEnum.BLOB.name(), mysqlVarBinaryProcessor),
Map.entry(MysqlColumnTypeEnum.LONGBLOB.name(), mysqlVarBinaryProcessor), Map.entry(MysqlColumnTypeEnum.LONGBLOB.name(), mysqlVarBinaryProcessor),
Map.entry(MysqlColumnTypeEnum.TINYBLOB.name(), mysqlVarBinaryProcessor), Map.entry(MysqlColumnTypeEnum.TINYBLOB.name(), mysqlVarBinaryProcessor),

View File

@ -1,10 +1,8 @@
package ai.chat2db.plugin.mysql.value.sub; package ai.chat2db.plugin.mysql.value.sub;
import ai.chat2db.plugin.mysql.value.template.MysqlDmlValueTemplate;
import ai.chat2db.spi.jdbc.DefaultValueProcessor; import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import ai.chat2db.spi.model.JDBCDataValue; import ai.chat2db.spi.model.JDBCDataValue;
import ai.chat2db.spi.model.SQLDataValue; import ai.chat2db.spi.model.SQLDataValue;
import com.google.common.io.BaseEncoding;
/** /**
* @author: zgq * @author: zgq
@ -26,6 +24,6 @@ public class MysqlBinaryProcessor extends DefaultValueProcessor {
@Override @Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) { public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return convertJDBCValueByType(dataValue); return dataValue.getBlobHexString();
} }
} }

View File

@ -40,7 +40,18 @@ public class MysqlBitProcessor extends DefaultValueProcessor {
@Override @Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) { public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return getString(convertJDBCValueByType(dataValue)); int precision = dataValue.getPrecision();
byte[] bytes = dataValue.getBytes();
if (precision == 1) {
//bit(1) [1 -> true] [0 -> false]
if (bytes.length == 1 && (bytes[0] == 0 || bytes[0] == 1)) {
return String.valueOf(dataValue.getBoolean());
}
// tinyint(1)
return String.valueOf(dataValue.getInt());
}
//bit(m) m: 2~64
return wrap(EasyStringUtils.getBitString(bytes, precision));
} }
public String getString(String value) { public String getString(String value) {

View File

@ -25,17 +25,17 @@ public class MysqlTextProcessor extends DefaultValueProcessor {
@Override @Override
public String convertJDBCValueByType(JDBCDataValue dataValue) { public String convertJDBCValueByType(JDBCDataValue dataValue) {
return getClobString(dataValue, true, super::convertJDBCValueByType); return getClobString(dataValue, super::convertJDBCValueByType);
} }
@Override @Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) { public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return wrap(getClobString(dataValue, false, super::convertJDBCValueStrByType)); return wrap(getClobString(dataValue, super::convertJDBCValueStrByType));
} }
private String getClobString(JDBCDataValue dataValue, boolean limitSize, Function<JDBCDataValue, String> function) { private String getClobString(JDBCDataValue dataValue, Function<JDBCDataValue, String> function) {
try { try {
return dataValue.getClobString(limitSize); return dataValue.getClobString();
} catch (Exception e) { } catch (Exception e) {
log.warn("convertJDBCValue error database: {} , error dataType: {} ", log.warn("convertJDBCValue error database: {} , error dataType: {} ",
Chat2DBContext.getDBConfig().getDbType(), dataValue.getType(), e); Chat2DBContext.getDBConfig().getDbType(), dataValue.getType(), e);

View File

@ -1,8 +1,10 @@
package ai.chat2db.plugin.mysql.value.sub; package ai.chat2db.plugin.mysql.value.sub;
import ai.chat2db.spi.jdbc.DefaultValueProcessor;
import ai.chat2db.spi.model.JDBCDataValue; import ai.chat2db.spi.model.JDBCDataValue;
import ai.chat2db.spi.model.SQLDataValue; import ai.chat2db.spi.model.SQLDataValue;
import ai.chat2db.spi.sql.Chat2DBContext; import ai.chat2db.spi.sql.Chat2DBContext;
import ch.qos.logback.core.model.processor.DefaultProcessor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/** /**
@ -10,7 +12,7 @@ import lombok.extern.slf4j.Slf4j;
* @date: 2024年06月03日 20:48 * @date: 2024年06月03日 20:48
*/ */
@Slf4j @Slf4j
public class MysqlVarBinaryProcessor extends MysqlBinaryProcessor { public class MysqlVarBinaryProcessor extends DefaultValueProcessor {
@Override @Override
public String convertSQLValueByType(SQLDataValue dataValue) { public String convertSQLValueByType(SQLDataValue dataValue) {
@ -22,9 +24,9 @@ public class MysqlVarBinaryProcessor extends MysqlBinaryProcessor {
@Override @Override
public String convertJDBCValueByType(JDBCDataValue dataValue) { public String convertJDBCValueByType(JDBCDataValue dataValue) {
try { try {
return dataValue.getBlobString(true); return dataValue.getBlobString();
} catch (Exception e) { } catch (Exception e) {
log.warn("convertJDBCValueByType error database: {} , error dataType: {} ", log.warn("convertJDBCValue error database: {} , error dataType: {} ",
Chat2DBContext.getDBConfig().getDbType(), dataValue.getType(), e); Chat2DBContext.getDBConfig().getDbType(), dataValue.getType(), e);
return super.convertJDBCValueByType(dataValue); return super.convertJDBCValueByType(dataValue);
} }
@ -33,7 +35,7 @@ public class MysqlVarBinaryProcessor extends MysqlBinaryProcessor {
@Override @Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) { public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return super.convertJDBCValueStrByType(dataValue); return dataValue.getBlobHexString();
} }
} }

View File

@ -21,7 +21,7 @@ public class OracleBlobProcessor extends DefaultValueProcessor {
@Override @Override
public String convertJDBCValueByType(JDBCDataValue dataValue) { public String convertJDBCValueByType(JDBCDataValue dataValue) {
try { try {
return dataValue.getBlobString(true); return dataValue.getBlobString();
} catch (Exception e) { } catch (Exception e) {
log.warn("convertJDBCValueByType error database: {} , error dataType: {} ", log.warn("convertJDBCValueByType error database: {} , error dataType: {} ",
Chat2DBContext.getDBConfig().getDbType(), dataValue.getType(), e); Chat2DBContext.getDBConfig().getDbType(), dataValue.getType(), e);

View File

@ -19,13 +19,13 @@ public class OracleClobProcessor extends DefaultValueProcessor {
@Override @Override
public String convertJDBCValueByType(JDBCDataValue dataValue) { public String convertJDBCValueByType(JDBCDataValue dataValue) {
return dataValue.getClobString(true); return dataValue.getClobString();
} }
@Override @Override
public String convertJDBCValueStrByType(JDBCDataValue dataValue) { public String convertJDBCValueStrByType(JDBCDataValue dataValue) {
return wrap(dataValue.getClobString(false)); return wrap(dataValue.getClobString());
} }
private String wrap(String value) { private String wrap(String value) {

View File

@ -14,7 +14,9 @@ import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.*; import java.sql.*;
import java.util.Objects;
/** /**
* @author: zgq * @author: zgq
@ -26,6 +28,7 @@ public class JDBCDataValue {
private ResultSet resultSet; private ResultSet resultSet;
private ResultSetMetaData metaData; private ResultSetMetaData metaData;
private int columnIndex; private int columnIndex;
private boolean limitSize;
public Object getObject() { public Object getObject() {
try { try {
@ -88,34 +91,54 @@ public class JDBCDataValue {
return ResultSetUtils.getBlob(resultSet, columnIndex); return ResultSetUtils.getBlob(resultSet, columnIndex);
} }
public String getBlobString(boolean limitSize) { public String getBlobString() {
//TODO: Identify more file types
Blob blob = getBlob(); Blob blob = getBlob();
LOBInfo blobInfo = getBlobInfo(blob); LOBInfo blobInfo = getBlobInfo(blob);
String unit = blobInfo.getUnit();
if (blobInfo.getSize() == 0) { if (blobInfo.getSize() == 0) {
return ""; return "";
} }
try {
InputStream binaryStream = blob.getBinaryStream(); try (InputStream binaryStream = blob.getBinaryStream()) {
Tika tika = new Tika(); Tika tika = new Tika();
String contentType = tika.detect(binaryStream); String contentType = tika.detect(binaryStream);
if ("image/jpeg".equals(contentType)) { FileTypeEnum fileTypeEnum = FileTypeEnum.fromDescription(contentType);
if (Objects.isNull(fileTypeEnum)) {
BufferedImage bufferedImage = ImageIO.read(binaryStream); if (limitSize && isBigSize(unit)) {
return String.format("[%s] %dx%d JPEG image %d %s", getType(), bufferedImage.getWidth(), bufferedImage.getHeight(), blobInfo.getSize(), blobInfo.getUnit()); return String.format("[%s] %d %s", getType(), blobInfo.getSize(), unit);
} else if ("text/plain".equals(contentType)) {
if (isBigSize(blobInfo.unit) && limitSize) {
return String.format("[%s] %d %s", getType(), blobInfo.size, blobInfo.unit);
} else {
return new String(binaryStream.readAllBytes());
} }
return getBlobHexString();
}
switch (fileTypeEnum) {
case IMAGE:
if (limitSize) {
try (InputStream imageStream = blob.getBinaryStream()) {
BufferedImage bufferedImage = ImageIO.read(imageStream);
return String.format("[%s] %dx%d JPEG image %d %s",
getType(), bufferedImage.getWidth(),
bufferedImage.getHeight(), blobInfo.getSize(), unit);
}
} else {
return getBlobHexString();
}
case STRING:
if (isBigSize(unit) && limitSize) {
return String.format("[%s] %d %s", getType(), blobInfo.getSize(), unit);
} else {
return new String(binaryStream.readAllBytes());
}
default:
if (isBigSize(unit) && limitSize) {
return String.format("[%s] %d %s", getType(), blobInfo.getSize(), unit);
}
return getBlobHexString();
} }
} catch (SQLException | IOException e) { } catch (SQLException | IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return getString();
} }
private LOBInfo getBlobInfo(Blob blob) { private LOBInfo getBlobInfo(Blob blob) {
try { try {
long size = blob.length(); long size = blob.length();
@ -125,7 +148,7 @@ public class JDBCDataValue {
} }
} }
public String getClobString(boolean limitSize) { public String getClobString() {
Clob clob = getClob(); Clob clob = getClob();
LOBInfo cLobInfo = getCLobInfo(clob); LOBInfo cLobInfo = getCLobInfo(clob);
int size = cLobInfo.getSize(); int size = cLobInfo.getSize();
@ -165,7 +188,7 @@ public class JDBCDataValue {
@NotNull @NotNull
private LOBInfo getLobInfo(long size) { private LOBInfo getLobInfo(long size) {
if (size == 0) { if (size == 0) {
return new LOBInfo(LobUnit.K.unit, 0); return new LOBInfo(LobUnit.B.unit, 0);
} }
return calculateSizeAndUnit(size); return calculateSizeAndUnit(size);
} }
@ -193,7 +216,7 @@ public class JDBCDataValue {
public String getBigDecimalString() { public String getBigDecimalString() {
BigDecimal bigDecimal = getBigDecimal(); BigDecimal bigDecimal = getBigDecimal();
return bigDecimal==null?new String(getBytes()):bigDecimal.toPlainString(); return bigDecimal == null ? new String(getBytes()) : bigDecimal.toPlainString();
} }
@Data @Data
@ -217,4 +240,25 @@ public class JDBCDataValue {
this.size = size; this.size = size;
} }
} }
@Getter
public enum FileTypeEnum {
IMAGE("image/jpeg"),
STRING("text/plain"),
;
private final String description;
FileTypeEnum(String description) {
this.description = description;
}
public static FileTypeEnum fromDescription(String description) {
for (FileTypeEnum fileType : values()) {
if (fileType.description.equals(description)) {
return fileType;
}
}
return null;
}
}
} }