修复mysql下update操作值带转义字符导致失败的bug

This commit is contained in:
Redkale
2019-07-12 16:52:46 +08:00
parent fc8fa27602
commit 27a587d31f
4 changed files with 71 additions and 25 deletions

View File

@@ -142,7 +142,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
if (obj != null && obj.getClass().isArray()) { if (obj != null && obj.getClass().isArray()) {
sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'"); sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'");
} else { } else {
sb.append(FilterNode.formatToString(obj)); sb.append(info.formatSQLValue(obj, sqlFormatter));
} }
} else { } else {
sb.append(ch); sb.append(ch);
@@ -290,7 +290,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
if (obj != null && obj.getClass().isArray()) { if (obj != null && obj.getClass().isArray()) {
sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'"); sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'");
} else { } else {
sb.append(FilterNode.formatToString(obj)); sb.append(info.formatSQLValue(obj, sqlFormatter));
} }
} else { } else {
sb.append(ch); sb.append(ch);

View File

@@ -59,6 +59,8 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
@Resource(name = "$") @Resource(name = "$")
protected DataCacheListener cacheListener; protected DataCacheListener cacheListener;
protected final BiFunction<EntityInfo, Object, CharSequence> sqlFormatter;
protected final BiConsumer futureCompleteConsumer = (r, t) -> { protected final BiConsumer futureCompleteConsumer = (r, t) -> {
if (t != null) logger.log(Level.SEVERE, "CompletableFuture complete error", (Throwable) t); if (t != null) logger.log(Level.SEVERE, "CompletableFuture complete error", (Throwable) t);
}; };
@@ -107,6 +109,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
Semaphore semaphore = maxconns > 0 ? new Semaphore(maxconns) : null; Semaphore semaphore = maxconns > 0 ? new Semaphore(maxconns) : null;
this.readPool = createPoolSource(this, "read", queue, semaphore, readprop); this.readPool = createPoolSource(this, "read", queue, semaphore, readprop);
this.writePool = createPoolSource(this, "write", queue, semaphore, writeprop); this.writePool = createPoolSource(this, "write", queue, semaphore, writeprop);
this.sqlFormatter = (info, val) -> formatValueToString(info, val);
} }
@Local @Local
@@ -284,7 +287,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
return null; return null;
} }
protected <T> String formatValueToString(final EntityInfo<T> info, Object value) { protected <T> CharSequence formatValueToString(final EntityInfo<T> info, Object value) {
final String dbtype = this.readPool.getDbtype(); final String dbtype = this.readPool.getDbtype();
if ("mysql".equals(dbtype)) { if ("mysql".equals(dbtype)) {
if (value == null) return null; if (value == null) return null;
@@ -296,7 +299,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
} }
return String.valueOf(value); return String.valueOf(value);
} }
return info.formatToString(value); return info.formatSQLValue(value, null);
} }
//----------------------------- insert ----------------------------- //----------------------------- insert -----------------------------
@@ -506,13 +509,13 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
protected <T> CompletableFuture<Integer> deleteCompose(final EntityInfo<T> info, final Serializable... pks) { protected <T> CompletableFuture<Integer> deleteCompose(final EntityInfo<T> info, final Serializable... pks) {
if (pks.length == 1) { if (pks.length == 1) {
String sql = "DELETE FROM " + info.getTable(pks[0]) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pks[0])); String sql = "DELETE FROM " + info.getTable(pks[0]) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pks[0], sqlFormatter);
return deleteDB(info, null, sql); return deleteDB(info, null, sql);
} }
String sql = "DELETE FROM " + info.getTable(pks[0]) + " WHERE " + info.getPrimarySQLColumn() + " IN ("; String sql = "DELETE FROM " + info.getTable(pks[0]) + " WHERE " + info.getPrimarySQLColumn() + " IN (";
for (int i = 0; i < pks.length; i++) { for (int i = 0; i < pks.length; i++) {
if (i > 0) sql += ','; if (i > 0) sql += ',';
sql += FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pks[i])); sql += info.formatSQLValue(info.getPrimarySQLColumn(), pks[i], sqlFormatter);
} }
sql += ")"; sql += ")";
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql); if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql);
@@ -795,11 +798,11 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
protected <T> CompletableFuture<Integer> updateColumnCompose(final EntityInfo<T> info, Serializable pk, String column, final Serializable colval) { protected <T> CompletableFuture<Integer> updateColumnCompose(final EntityInfo<T> info, Serializable pk, String column, final Serializable colval) {
if (colval instanceof byte[]) { if (colval instanceof byte[]) {
String sql = "UPDATE " + info.getTable(pk) + " SET " + info.getSQLColumn(null, column) + " = " + prepareParamSign(1) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk)); String sql = "UPDATE " + info.getTable(pk) + " SET " + info.getSQLColumn(null, column) + " = " + prepareParamSign(1) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
return updateDB(info, null, sql, true, colval); return updateDB(info, null, sql, true, colval);
} else { } else {
String sql = "UPDATE " + info.getTable(pk) + " SET " + info.getSQLColumn(null, column) + " = " String sql = "UPDATE " + info.getTable(pk) + " SET " + info.getSQLColumn(null, column) + " = "
+ formatValueToString(info, info.getSQLValue(column, colval)) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk)); + info.formatSQLValue(column, colval, sqlFormatter) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
return updateDB(info, null, sql, false); return updateDB(info, null, sql, false);
} }
} }
@@ -871,7 +874,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
return updateDB(info, null, sql, true, colval); return updateDB(info, null, sql, true, colval);
} else { } else {
String sql = "UPDATE " + info.getTable(node) + " a " + (join1 == null ? "" : (", " + join1)) String sql = "UPDATE " + info.getTable(node) + " a " + (join1 == null ? "" : (", " + join1))
+ " SET " + info.getSQLColumn(alias, column) + " = " + formatValueToString(info, colval) + " SET " + info.getSQLColumn(alias, column) + " = " + info.formatSQLValue(colval, sqlFormatter)
+ ((where == null || where.length() == 0) ? (join2 == null ? "" : (" WHERE " + join2)) + ((where == null || where.length() == 0) ? (join2 == null ? "" : (" WHERE " + join2))
: (" WHERE " + where + (join2 == null ? "" : (" AND " + join2)))); : (" WHERE " + where + (join2 == null ? "" : (" AND " + join2))));
return updateDB(info, null, sql, false); return updateDB(info, null, sql, false);
@@ -940,11 +943,11 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
blobs.add((byte[]) col.getValue()); blobs.add((byte[]) col.getValue());
setsql.append(c).append(" = ").append(prepareParamSign(++index)); setsql.append(c).append(" = ").append(prepareParamSign(++index));
} else { } else {
setsql.append(c).append(" = ").append(info.formatSQLValue(c, attr, col)); setsql.append(c).append(" = ").append(info.formatSQLValue(c, attr, col, sqlFormatter));
} }
} }
if (setsql.length() < 1) return CompletableFuture.completedFuture(0); if (setsql.length() < 1) return CompletableFuture.completedFuture(0);
String sql = "UPDATE " + info.getTable(pk) + " SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk)); String sql = "UPDATE " + info.getTable(pk) + " SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
if (blobs == null) return updateDB(info, null, sql, false); if (blobs == null) return updateDB(info, null, sql, false);
return updateDB(info, null, sql, true, blobs.toArray()); return updateDB(info, null, sql, true, blobs.toArray());
} }
@@ -1022,7 +1025,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
blobs.add((byte[]) col.getValue()); blobs.add((byte[]) col.getValue());
setsql.append(c).append(" = ").append(prepareParamSign(++index)); setsql.append(c).append(" = ").append(prepareParamSign(++index));
} else { } else {
setsql.append(c).append(" = ").append(info.formatSQLValue(c, attr, col)); setsql.append(c).append(" = ").append(info.formatSQLValue(c, attr, col, sqlFormatter));
} }
} }
if (setsql.length() < 1) return CompletableFuture.completedFuture(0); if (setsql.length() < 1) return CompletableFuture.completedFuture(0);
@@ -1157,7 +1160,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
blobs.add((byte[]) val); blobs.add((byte[]) val);
setsql.append(" = ").append(prepareParamSign(++index)); setsql.append(" = ").append(prepareParamSign(++index));
} else { } else {
setsql.append(" = ").append(formatValueToString(info, val)); setsql.append(" = ").append(info.formatSQLValue(val, sqlFormatter));
} }
} }
if (neednode) { if (neednode) {
@@ -1178,7 +1181,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
return updateDB(info, null, sql, true, blobs.toArray()); return updateDB(info, null, sql, true, blobs.toArray());
} else { } else {
final Serializable id = (Serializable) info.getSQLValue(info.getPrimary(), entity); final Serializable id = (Serializable) info.getSQLValue(info.getPrimary(), entity);
String sql = "UPDATE " + info.getTable(id) + " a SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(id); String sql = "UPDATE " + info.getTable(id) + " a SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(id, sqlFormatter);
if (blobs == null) return updateDB(info, null, sql, false); if (blobs == null) return updateDB(info, null, sql, false);
return updateDB(info, null, sql, true, blobs.toArray()); return updateDB(info, null, sql, true, blobs.toArray());
} }
@@ -1557,7 +1560,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
protected <T> CompletableFuture<T> findCompose(final EntityInfo<T> info, final SelectColumn selects, Serializable pk) { protected <T> CompletableFuture<T> findCompose(final EntityInfo<T> info, final SelectColumn selects, Serializable pk) {
String column = info.getPrimarySQLColumn(); String column = info.getPrimarySQLColumn();
final String sql = "SELECT " + info.getQueryColumns(null, selects) + " FROM " + info.getTable(pk) + " WHERE " + column + " = " + FilterNode.formatToString(info.getSQLValue(column, pk)); final String sql = "SELECT " + info.getQueryColumns(null, selects) + " FROM " + info.getTable(pk) + " WHERE " + column + " = " + info.formatSQLValue(column, pk, sqlFormatter);
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " find sql=" + sql); if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " find sql=" + sql);
return findDB(info, sql, true, selects); return findDB(info, sql, true, selects);
} }
@@ -1694,7 +1697,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
} }
protected <T> CompletableFuture<Serializable> findColumnCompose(final EntityInfo<T> info, String column, final Serializable defValue, final Serializable pk) { protected <T> CompletableFuture<Serializable> findColumnCompose(final EntityInfo<T> info, String column, final Serializable defValue, final Serializable pk) {
final String sql = "SELECT " + info.getSQLColumn(null, column) + " FROM " + info.getTable(pk) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk)); final String sql = "SELECT " + info.getSQLColumn(null, column) + " FROM " + info.getTable(pk) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " find sql=" + sql); if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " find sql=" + sql);
return findColumnDB(info, sql, true, column, defValue); return findColumnDB(info, sql, true, column, defValue);
} }
@@ -1756,7 +1759,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
} }
protected <T> CompletableFuture<Boolean> existsCompose(final EntityInfo<T> info, Serializable pk) { protected <T> CompletableFuture<Boolean> existsCompose(final EntityInfo<T> info, Serializable pk) {
final String sql = "SELECT COUNT(*) FROM " + info.getTable(pk) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk)); final String sql = "SELECT COUNT(*) FROM " + info.getTable(pk) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " exists sql=" + sql); if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " exists sql=" + sql);
return existsDB(info, sql, true); return existsDB(info, sql, true);
} }

View File

@@ -894,9 +894,36 @@ public final class EntityInfo<T> {
return handler.encrypt(fieldvalue); return handler.encrypt(fieldvalue);
} }
/**
* 字段值转换成带转义的数据库的值
*
* @param fieldname 字段名
* @param fieldvalue 字段值
* @param sqlFormatter 转义器
*
* @return CharSequence
*/
public CharSequence formatSQLValue(String fieldname, Serializable fieldvalue, BiFunction<EntityInfo, Object, CharSequence> sqlFormatter) {
Object val = getSQLValue(fieldname, fieldvalue);
return sqlFormatter == null ? formatToString(val) : sqlFormatter.apply(this, val);
}
/**
* 字段值转换成带转义的数据库的值
*
* @param value 字段值
* @param sqlFormatter 转义器
*
* @return CharSequence
*/
public CharSequence formatSQLValue(Object value, BiFunction<EntityInfo, Object, CharSequence> sqlFormatter) {
return sqlFormatter == null ? formatToString(value) : sqlFormatter.apply(this, value);
}
/** /**
* 字段值转换成数据库的值 * 字段值转换成数据库的值
* *
* @param <F> 泛型
* @param attr Attribute * @param attr Attribute
* @param entity 记录对象 * @param entity 记录对象
* *
@@ -909,6 +936,21 @@ public final class EntityInfo<T> {
return val; return val;
} }
/**
* 字段值转换成带转义的数据库的值
*
* @param <F> 泛型
* @param attr Attribute
* @param entity 记录对象
* @param sqlFormatter 转义器
*
* @return CharSequence
*/
public <F> CharSequence formatSQLValue(Attribute<T, F> attr, T entity, BiFunction<EntityInfo, Object, CharSequence> sqlFormatter) {
Object val = getSQLValue(attr, entity);
return sqlFormatter == null ? formatToString(val) : sqlFormatter.apply(this, val);
}
/** /**
* 数据库的值转换成数字段值 * 数据库的值转换成数字段值
* *
@@ -950,10 +992,11 @@ public final class EntityInfo<T> {
* @param col 表字段名 * @param col 表字段名
* @param attr Attribute * @param attr Attribute
* @param cv ColumnValue * @param cv ColumnValue
* @param formatter 转义器
* *
* @return CharSequence * @return CharSequence
*/ */
protected CharSequence formatSQLValue(String col, Attribute<T, Serializable> attr, final ColumnValue cv) { protected CharSequence formatSQLValue(String col, Attribute<T, Serializable> attr, final ColumnValue cv, BiFunction<EntityInfo, Object, CharSequence> formatter) {
if (cv == null) return null; if (cv == null) return null;
Object val = cv.getValue(); Object val = cv.getValue();
CryptHandler handler = attr.attach(); CryptHandler handler = attr.attach();
@@ -968,9 +1011,9 @@ public final class EntityInfo<T> {
case ORR: case ORR:
return new StringBuilder().append(col).append(" | ").append(val); return new StringBuilder().append(col).append(" | ").append(val);
case MOV: case MOV:
return formatToString(val); return formatter == null ? formatToString(val) : formatter.apply(this, val);
} }
return formatToString(val); return formatter == null ? formatToString(val) : formatter.apply(this, val);
} }
/** /**
@@ -1021,7 +1064,7 @@ public final class EntityInfo<T> {
* *
* @return String * @return String
*/ */
protected String formatToString(Object value) { private String formatToString(Object value) {
if (value == null) return null; if (value == null) return null;
if (value instanceof CharSequence) { if (value instanceof CharSequence) {
return new StringBuilder().append('\'').append(value.toString().replace("'", "\\'")).append('\'').toString(); return new StringBuilder().append('\'').append(value.toString().replace("'", "\\'")).append('\'').toString();

View File

@@ -1811,7 +1811,7 @@ public class FilterNode { //FilterNode 不能实现Serializable接口 否则
return sb; return sb;
} }
protected static CharSequence formatToString(Object value) { private static CharSequence formatToString(Object value) {
CharSequence sb = formatToString(null, value); CharSequence sb = formatToString(null, value);
return sb == null ? null : sb.toString(); return sb == null ? null : sb.toString();
} }