|
@@ -4,6 +4,7 @@ import org.dbsyncer.common.event.RowChangedEvent;
|
|
import org.dbsyncer.common.util.CollectionUtils;
|
|
import org.dbsyncer.common.util.CollectionUtils;
|
|
import org.dbsyncer.common.util.StringUtil;
|
|
import org.dbsyncer.common.util.StringUtil;
|
|
import org.dbsyncer.connector.constant.ConnectorConstant;
|
|
import org.dbsyncer.connector.constant.ConnectorConstant;
|
|
|
|
+import org.dbsyncer.connector.database.AbstractDatabaseConnector;
|
|
import org.dbsyncer.connector.database.DatabaseConnectorMapper;
|
|
import org.dbsyncer.connector.database.DatabaseConnectorMapper;
|
|
import org.dbsyncer.connector.model.Field;
|
|
import org.dbsyncer.connector.model.Field;
|
|
import org.dbsyncer.connector.model.MetaInfo;
|
|
import org.dbsyncer.connector.model.MetaInfo;
|
|
@@ -11,8 +12,11 @@ import org.dbsyncer.connector.model.Table;
|
|
import org.dbsyncer.connector.util.PrimaryKeyUtil;
|
|
import org.dbsyncer.connector.util.PrimaryKeyUtil;
|
|
import org.springframework.util.Assert;
|
|
import org.springframework.util.Assert;
|
|
|
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
+import java.util.Set;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -60,29 +64,33 @@ public abstract class AbstractDatabaseExtractor extends AbstractExtractor {
|
|
*/
|
|
*/
|
|
protected void postProcessDqlBeforeInitialization() {
|
|
protected void postProcessDqlBeforeInitialization() {
|
|
DatabaseConnectorMapper mapper = (DatabaseConnectorMapper) connectorFactory.connect(connectorConfig);
|
|
DatabaseConnectorMapper mapper = (DatabaseConnectorMapper) connectorFactory.connect(connectorConfig);
|
|
- for (Table table : sourceTable) {
|
|
|
|
- String sql = table.getSql();
|
|
|
|
- String tableName = table.getName();
|
|
|
|
- String primaryKey = PrimaryKeyUtil.findOriginalTablePrimaryKey(table);
|
|
|
|
|
|
+ AbstractDatabaseConnector connector = (AbstractDatabaseConnector) connectorFactory.getConnector(mapper);
|
|
|
|
+ String quotation = connector.buildSqlWithQuotation();
|
|
|
|
+
|
|
|
|
+ Map<String, String> tableMap = new HashMap<>();
|
|
|
|
+ mapper.getConfig().getSqlTables().forEach(s -> tableMap.put(s.getSqlName(), s.getTable()));
|
|
|
|
+
|
|
|
|
+ for (Table t : sourceTable) {
|
|
|
|
+ String sql = t.getSql();
|
|
|
|
+ String sqlName = t.getName();
|
|
|
|
+ Set<String> primaryKeys = PrimaryKeyUtil.findOriginalTablePrimaryKey(t);
|
|
|
|
+ String tableName = tableMap.get(sqlName);
|
|
Assert.hasText(sql, "The sql is null.");
|
|
Assert.hasText(sql, "The sql is null.");
|
|
Assert.hasText(tableName, "The tableName is null.");
|
|
Assert.hasText(tableName, "The tableName is null.");
|
|
- Assert.hasText(primaryKey, "The primaryKey is null.");
|
|
|
|
|
|
|
|
- MetaInfo metaInfo = connectorFactory.getMetaInfo(mapper, tableName);
|
|
|
|
|
|
+ MetaInfo metaInfo = connectorFactory.getMetaInfo(mapper, sqlName);
|
|
final List<Field> column = metaInfo.getColumn();
|
|
final List<Field> column = metaInfo.getColumn();
|
|
- Assert.notEmpty(column, String.format("The column of table name '%s' is empty.", tableName));
|
|
|
|
|
|
+ Assert.notEmpty(column, String.format("The column of table name '%s' is empty.", sqlName));
|
|
|
|
|
|
sql = sql.toUpperCase().replace("\t", " ");
|
|
sql = sql.toUpperCase().replace("\t", " ");
|
|
sql = sql.replace("\r", " ");
|
|
sql = sql.replace("\r", " ");
|
|
sql = sql.replace("\n", " ");
|
|
sql = sql.replace("\n", " ");
|
|
- StringBuilder querySql = new StringBuilder(table.getSql());
|
|
|
|
- if (StringUtil.contains(sql, " WHERE ")) {
|
|
|
|
- querySql.append(" AND ");
|
|
|
|
- } else {
|
|
|
|
- querySql.append(" WHERE ");
|
|
|
|
- }
|
|
|
|
- querySql.append(primaryKey).append("=?");
|
|
|
|
- DqlMapper dqlMapper = new DqlMapper(mapper, querySql.toString(), tableName, column, getPKIndex(column, primaryKey));
|
|
|
|
|
|
+
|
|
|
|
+ StringBuilder querySql = new StringBuilder(sql);
|
|
|
|
+ boolean notContainsWhere = !StringUtil.contains(sql, " WHERE ");
|
|
|
|
+ querySql.append(notContainsWhere ? " WHERE " : " AND ");
|
|
|
|
+ PrimaryKeyUtil.buildSql(querySql, primaryKeys, quotation, " AND ", " = ? ", notContainsWhere);
|
|
|
|
+ DqlMapper dqlMapper = new DqlMapper(mapper, querySql.toString(), column, getPrimaryKeyIndexArray(column, primaryKeys));
|
|
dqlMap.putIfAbsent(tableName, dqlMapper);
|
|
dqlMap.putIfAbsent(tableName, dqlMapper);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -91,26 +99,31 @@ public abstract class AbstractDatabaseExtractor extends AbstractExtractor {
|
|
* 获取主表主键索引
|
|
* 获取主表主键索引
|
|
*
|
|
*
|
|
* @param column
|
|
* @param column
|
|
- * @param primaryKey
|
|
|
|
|
|
+ * @param primaryKeys
|
|
* @return
|
|
* @return
|
|
*/
|
|
*/
|
|
- protected int getPKIndex(List<Field> column, String primaryKey) {
|
|
|
|
- int pkIndex = 0;
|
|
|
|
- boolean findPkIndex = false;
|
|
|
|
|
|
+ protected Integer[] getPrimaryKeyIndexArray(List<Field> column, Set<String> primaryKeys) {
|
|
|
|
+ List<Integer> indexList = new ArrayList<>();
|
|
for (Field f : column) {
|
|
for (Field f : column) {
|
|
- if (f.getName().equals(primaryKey)) {
|
|
|
|
- pkIndex = column.indexOf(f);
|
|
|
|
- findPkIndex = true;
|
|
|
|
- break;
|
|
|
|
|
|
+ if (primaryKeys.contains(f.getName())) {
|
|
|
|
+ indexList.add(column.indexOf(f));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- Assert.isTrue(findPkIndex, "The primaryKey is invalid.");
|
|
|
|
- return pkIndex;
|
|
|
|
|
|
+ Assert.isTrue(!CollectionUtils.isEmpty(indexList), "The primaryKeys is invalid.");
|
|
|
|
+ Integer[] indexArray = (Integer[]) indexList.toArray();
|
|
|
|
+ return indexArray;
|
|
}
|
|
}
|
|
|
|
|
|
private List<Object> queryDqlData(DqlMapper dqlMapper, List<Object> data) {
|
|
private List<Object> queryDqlData(DqlMapper dqlMapper, List<Object> data) {
|
|
if (!CollectionUtils.isEmpty(data)) {
|
|
if (!CollectionUtils.isEmpty(data)) {
|
|
- Map<String, Object> row = dqlMapper.mapper.execute(databaseTemplate -> databaseTemplate.queryForMap(dqlMapper.sql, data.get(dqlMapper.pkIndex)));
|
|
|
|
|
|
+ Map<String, Object> row = dqlMapper.mapper.execute(databaseTemplate -> {
|
|
|
|
+ int size = dqlMapper.primaryKeyIndexArray.length;
|
|
|
|
+ Object[] args = new Object[size];
|
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
|
+ args[i] = data.get(dqlMapper.primaryKeyIndexArray[i]);
|
|
|
|
+ }
|
|
|
|
+ return databaseTemplate.queryForMap(dqlMapper.sql, args);
|
|
|
|
+ });
|
|
if (!CollectionUtils.isEmpty(row)) {
|
|
if (!CollectionUtils.isEmpty(row)) {
|
|
data.clear();
|
|
data.clear();
|
|
dqlMapper.column.forEach(field -> data.add(row.get(field.getName())));
|
|
dqlMapper.column.forEach(field -> data.add(row.get(field.getName())));
|
|
@@ -122,15 +135,13 @@ public abstract class AbstractDatabaseExtractor extends AbstractExtractor {
|
|
final class DqlMapper {
|
|
final class DqlMapper {
|
|
DatabaseConnectorMapper mapper;
|
|
DatabaseConnectorMapper mapper;
|
|
String sql;
|
|
String sql;
|
|
- String tableName;
|
|
|
|
List<Field> column;
|
|
List<Field> column;
|
|
- int pkIndex;
|
|
|
|
|
|
+ Integer[] primaryKeyIndexArray;
|
|
|
|
|
|
- public DqlMapper(DatabaseConnectorMapper mapper, String sql, String tableName, List<Field> column, int pkIndex) {
|
|
|
|
|
|
+ public DqlMapper(DatabaseConnectorMapper mapper, String sql, List<Field> column, Integer[] primaryKeyIndexArray) {
|
|
this.mapper = mapper;
|
|
this.mapper = mapper;
|
|
- this.tableName = tableName;
|
|
|
|
this.column = column;
|
|
this.column = column;
|
|
- this.pkIndex = pkIndex;
|
|
|
|
|
|
+ this.primaryKeyIndexArray = primaryKeyIndexArray;
|
|
this.sql = sql;
|
|
this.sql = sql;
|
|
}
|
|
}
|
|
}
|
|
}
|