浏览代码

新增DqlPostgreSQL

AE86 3 年之前
父节点
当前提交
5f9a0bb457

+ 22 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/DqlPostgreSQLConfigChecker.java

@@ -0,0 +1,22 @@
+package org.dbsyncer.biz.checker.impl.connector;
+
+import org.dbsyncer.connector.config.DatabaseConfig;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/4/5 22:14
+ */
+@Component
+public class DqlPostgreSQLConfigChecker extends AbstractDataBaseConfigChecker {
+
+    @Override
+    public void modify(DatabaseConfig connectorConfig, Map<String, String> params) {
+        super.modify(connectorConfig, params);
+        super.modifyDql(connectorConfig, params);
+        super.modifySchema(connectorConfig, params);
+    }
+}

+ 125 - 193
dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/AbstractDatabaseConnector.java

@@ -219,136 +219,6 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
         return map;
     }
 
-    private void forceUpdate(Result result, DatabaseConnectorMapper connectorMapper, WriterBatchConfig config, Field pkField,
-                             Map row) {
-        String event = config.getEvent();
-        if (!config.isForceUpdate()) {
-            result.getFailData().add(row);
-            result.getError().append("SQL:").append(config.getCommand().get(event)).append(System.lineSeparator())
-                    .append("DATA:").append(row).append(System.lineSeparator())
-                    .append("ERROR:").append("Row data does not exist.").append(System.lineSeparator());
-            return;
-        }
-
-        // 不存在转insert
-        if (isUpdate(event)) {
-            String queryCount = config.getCommand().get(ConnectorConstant.OPERTION_QUERY_COUNT_EXIST);
-            if (!existRow(connectorMapper, queryCount, row.get(pkField.getName()))) {
-                logger.warn("{}表执行{}失败, 尝试执行{}, {}", config.getTableName(), event, ConnectorConstant.OPERTION_INSERT, row);
-                writer(result, connectorMapper, config, pkField, row, ConnectorConstant.OPERTION_INSERT);
-            }
-            return;
-        }
-
-        // 存在转update
-        if (isInsert(config.getEvent())) {
-            logger.warn("{}表执行{}失败, 尝试执行{}, {}", config.getTableName(), event, ConnectorConstant.OPERTION_UPDATE, row);
-            writer(result, connectorMapper, config, pkField, row, ConnectorConstant.OPERTION_UPDATE);
-        }
-    }
-
-    private void writer(Result result, DatabaseConnectorMapper connectorMapper, WriterBatchConfig config, Field pkField, Map row,
-                        String event) {
-        // 1、获取 SQL
-        String sql = config.getCommand().get(event);
-
-        List<Field> fields = new ArrayList<>(config.getFields());
-        // Update / Delete
-        if (!isInsert(event)) {
-            if (isDelete(event)) {
-                fields.clear();
-            }
-            fields.add(pkField);
-        }
-
-        try {
-            // 2、设置参数
-            int execute = connectorMapper.execute(databaseTemplate ->
-                    databaseTemplate.update(sql, (ps) ->
-                            batchRowsSetter(databaseTemplate.getConnection(), ps, fields, row)
-                    )
-            );
-            if (execute == 0) {
-                throw new ConnectorException(String.format("尝试执行[%s]失败", event));
-            }
-            result.getSuccessData().add(row);
-        } catch (Exception e) {
-            result.getFailData().add(row);
-            result.getError().append("SQL:").append(sql).append(System.lineSeparator())
-                    .append("DATA:").append(row).append(System.lineSeparator())
-                    .append("ERROR:").append(e.getMessage()).append(System.lineSeparator());
-            logger.error("执行{}失败: {}, DATA:{}", event, e.getMessage(), row);
-        }
-    }
-
-    /**
-     * 获取DQL表信息
-     *
-     * @param config
-     * @return
-     */
-    protected List<Table> getDqlTable(DatabaseConnectorMapper config) {
-        MetaInfo metaInfo = getDqlMetaInfo(config);
-        Assert.notNull(metaInfo, "SQL解析异常.");
-        DatabaseConfig cfg = config.getConfig();
-        List<Table> tables = new ArrayList<>();
-        tables.add(new Table(cfg.getSql()));
-        return tables;
-    }
-
-    /**
-     * 获取DQL元信息
-     *
-     * @param config
-     * @return
-     */
-    protected MetaInfo getDqlMetaInfo(DatabaseConnectorMapper config) {
-        DatabaseConfig cfg = config.getConfig();
-        String sql = cfg.getSql().toUpperCase();
-        String queryMetaSql = StringUtil.contains(sql, " WHERE ") ? sql + " AND 1!=1 " : sql + " WHERE 1!=1 ";
-        return config.execute(databaseTemplate -> getMetaInfo(databaseTemplate, queryMetaSql, cfg.getTable()));
-    }
-
-    /**
-     * 获取DQL源配置
-     *
-     * @param commandConfig
-     * @param appendGroupByPK
-     * @return
-     */
-    protected Map<String, String> getDqlSourceCommand(CommandConfig commandConfig, boolean appendGroupByPK) {
-        // 获取过滤SQL
-        List<Filter> filter = commandConfig.getFilter();
-        String queryFilterSql = getQueryFilterSql(filter);
-
-        // 获取查询SQL
-        Table table = commandConfig.getTable();
-        Map<String, String> map = new HashMap<>();
-        String querySql = table.getName();
-
-        // 存在条件
-        if (StringUtil.isNotBlank(queryFilterSql)) {
-            querySql += queryFilterSql;
-        }
-        String quotation = buildSqlWithQuotation();
-        String pk = findTablePrimaryKey(commandConfig.getOriginalTable(), quotation);
-        map.put(SqlBuilderEnum.QUERY.getName(), getPageSql(new PageSqlConfig(querySql, pk)));
-
-        // 获取查询总数SQL
-        StringBuilder queryCount = new StringBuilder();
-        queryCount.append("SELECT COUNT(1) FROM (").append(table.getName());
-        if (StringUtil.isNotBlank(queryFilterSql)) {
-            queryCount.append(queryFilterSql);
-        }
-        // Mysql
-        if (appendGroupByPK) {
-            queryCount.append(" GROUP BY ").append(pk);
-        }
-        queryCount.append(") DBSYNCER_T");
-        map.put(ConnectorConstant.OPERTION_QUERY_COUNT, queryCount.toString());
-        return map;
-    }
-
     /**
      * 查询语句表名和字段带上引号(默认不加)
      *
@@ -455,67 +325,6 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
         return "select 1";
     }
 
-    /**
-     * 根据过滤条件获取查询SQL
-     *
-     * @param queryOperator and/or
-     * @param filter
-     * @return
-     */
-    private String getFilterSql(String queryOperator, List<Filter> filter) {
-        List<Filter> list = filter.stream().filter(f -> StringUtil.equals(f.getOperation(), queryOperator)).collect(Collectors.toList());
-        if (CollectionUtils.isEmpty(list)) {
-            return "";
-        }
-
-        int size = list.size();
-        int end = size - 1;
-        StringBuilder sql = new StringBuilder();
-        sql.append("(");
-        Filter c = null;
-        String quotation = buildSqlWithQuotation();
-        for (int i = 0; i < size; i++) {
-            c = list.get(i);
-            // "USER" = 'zhangsan'
-            sql.append(quotation).append(c.getName()).append(quotation).append(c.getFilter()).append("'").append(c.getValue()).append("'");
-            if (i < end) {
-                sql.append(" ").append(queryOperator).append(" ");
-            }
-        }
-        sql.append(")");
-        return sql.toString();
-    }
-
-    /**
-     * @param connection 连接
-     * @param ps         参数构造器
-     * @param fields     同步字段,例如[{name=ID, type=4}, {name=NAME, type=12}]
-     * @param row        同步字段对应的值,例如{ID=123, NAME=张三11}
-     */
-    private void batchRowsSetter(Connection connection, PreparedStatement ps, List<Field> fields, Map row) {
-        Field f = null;
-        int type;
-        Object val = null;
-        int size = fields.size();
-        for (int i = 0; i < size; i++) {
-            // 取出字段和对应值
-            f = fields.get(i);
-            type = f.getType();
-            val = row.get(f.getName());
-            SetterEnum.getSetter(type).set(connection, ps, i + 1, type, val);
-        }
-    }
-
-    private boolean existRow(DatabaseConnectorMapper connectorMapper, String sql, Object value) {
-        int rowNum = 0;
-        try {
-            rowNum = connectorMapper.execute(databaseTemplate -> databaseTemplate.queryForObject(sql, new Object[] {value}, Integer.class));
-        } catch (Exception e) {
-            logger.error("检查数据行存在异常:{},SQL:{},参数:{}", e.getMessage(), sql, value);
-        }
-        return rowNum > 0;
-    }
-
     /**
      * 获取数据库表元数据信息
      *
@@ -524,7 +333,7 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
      * @param tableName        表名
      * @return
      */
-    private MetaInfo getMetaInfo(DatabaseTemplate databaseTemplate, String metaSql, String tableName) throws SQLException {
+    protected MetaInfo getMetaInfo(DatabaseTemplate databaseTemplate, String metaSql, String tableName) throws SQLException {
         SqlRowSet sqlRowSet = databaseTemplate.queryForRowSet(metaSql);
         ResultSetWrappingSqlRowSet rowSet = (ResultSetWrappingSqlRowSet) sqlRowSet;
         SqlRowSetMetaData metaData = rowSet.getMetaData();
@@ -569,7 +378,7 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
      * @param quotation
      * @return
      */
-    private String findTablePrimaryKey(Table table, String quotation) {
+    protected String findTablePrimaryKey(Table table, String quotation) {
         if (null != table) {
             List<Field> column = table.getColumn();
             if (!CollectionUtils.isEmpty(column)) {
@@ -586,6 +395,129 @@ public abstract class AbstractDatabaseConnector extends AbstractConnector
         return "";
     }
 
+    /**
+     * 根据过滤条件获取查询SQL
+     *
+     * @param queryOperator and/or
+     * @param filter
+     * @return
+     */
+    private String getFilterSql(String queryOperator, List<Filter> filter) {
+        List<Filter> list = filter.stream().filter(f -> StringUtil.equals(f.getOperation(), queryOperator)).collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(list)) {
+            return "";
+        }
+
+        int size = list.size();
+        int end = size - 1;
+        StringBuilder sql = new StringBuilder();
+        sql.append("(");
+        Filter c = null;
+        String quotation = buildSqlWithQuotation();
+        for (int i = 0; i < size; i++) {
+            c = list.get(i);
+            // "USER" = 'zhangsan'
+            sql.append(quotation).append(c.getName()).append(quotation).append(c.getFilter()).append("'").append(c.getValue()).append("'");
+            if (i < end) {
+                sql.append(" ").append(queryOperator).append(" ");
+            }
+        }
+        sql.append(")");
+        return sql.toString();
+    }
+
+    /**
+     * @param connection 连接
+     * @param ps         参数构造器
+     * @param fields     同步字段,例如[{name=ID, type=4}, {name=NAME, type=12}]
+     * @param row        同步字段对应的值,例如{ID=123, NAME=张三11}
+     */
+    private void batchRowsSetter(Connection connection, PreparedStatement ps, List<Field> fields, Map row) {
+        Field f = null;
+        int type;
+        Object val = null;
+        int size = fields.size();
+        for (int i = 0; i < size; i++) {
+            // 取出字段和对应值
+            f = fields.get(i);
+            type = f.getType();
+            val = row.get(f.getName());
+            SetterEnum.getSetter(type).set(connection, ps, i + 1, type, val);
+        }
+    }
+
+    private void forceUpdate(Result result, DatabaseConnectorMapper connectorMapper, WriterBatchConfig config, Field pkField,
+                             Map row) {
+        String event = config.getEvent();
+        if (!config.isForceUpdate()) {
+            result.getFailData().add(row);
+            result.getError().append("SQL:").append(config.getCommand().get(event)).append(System.lineSeparator())
+                    .append("DATA:").append(row).append(System.lineSeparator())
+                    .append("ERROR:").append("Row data does not exist.").append(System.lineSeparator());
+            return;
+        }
+
+        // 不存在转insert
+        if (isUpdate(event)) {
+            String queryCount = config.getCommand().get(ConnectorConstant.OPERTION_QUERY_COUNT_EXIST);
+            if (!existRow(connectorMapper, queryCount, row.get(pkField.getName()))) {
+                logger.warn("{}表执行{}失败, 尝试执行{}, {}", config.getTableName(), event, ConnectorConstant.OPERTION_INSERT, row);
+                writer(result, connectorMapper, config, pkField, row, ConnectorConstant.OPERTION_INSERT);
+            }
+            return;
+        }
+
+        // 存在转update
+        if (isInsert(config.getEvent())) {
+            logger.warn("{}表执行{}失败, 尝试执行{}, {}", config.getTableName(), event, ConnectorConstant.OPERTION_UPDATE, row);
+            writer(result, connectorMapper, config, pkField, row, ConnectorConstant.OPERTION_UPDATE);
+        }
+    }
+
+    private void writer(Result result, DatabaseConnectorMapper connectorMapper, WriterBatchConfig config, Field pkField, Map row,
+                        String event) {
+        // 1、获取 SQL
+        String sql = config.getCommand().get(event);
+
+        List<Field> fields = new ArrayList<>(config.getFields());
+        // Update / Delete
+        if (!isInsert(event)) {
+            if (isDelete(event)) {
+                fields.clear();
+            }
+            fields.add(pkField);
+        }
+
+        try {
+            // 2、设置参数
+            int execute = connectorMapper.execute(databaseTemplate ->
+                    databaseTemplate.update(sql, (ps) ->
+                            batchRowsSetter(databaseTemplate.getConnection(), ps, fields, row)
+                    )
+            );
+            if (execute == 0) {
+                throw new ConnectorException(String.format("尝试执行[%s]失败", event));
+            }
+            result.getSuccessData().add(row);
+        } catch (Exception e) {
+            result.getFailData().add(row);
+            result.getError().append("SQL:").append(sql).append(System.lineSeparator())
+                    .append("DATA:").append(row).append(System.lineSeparator())
+                    .append("ERROR:").append(e.getMessage()).append(System.lineSeparator());
+            logger.error("执行{}失败: {}, DATA:{}", event, e.getMessage(), row);
+        }
+    }
+
+    private boolean existRow(DatabaseConnectorMapper connectorMapper, String sql, Object value) {
+        int rowNum = 0;
+        try {
+            rowNum = connectorMapper.execute(databaseTemplate -> databaseTemplate.queryForObject(sql, new Object[]{value}, Integer.class));
+        } catch (Exception e) {
+            logger.error("检查数据行存在异常:{},SQL:{},参数:{}", e.getMessage(), sql, value);
+        }
+        return rowNum > 0;
+    }
+
     private boolean isPk(Map<String, List<String>> tables, String tableName, String name) {
         List<String> pk = tables.get(tableName);
         return !CollectionUtils.isEmpty(pk) && pk.contains(name);

+ 7 - 2
dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/ConnectorEnum.java

@@ -13,6 +13,7 @@ import org.dbsyncer.connector.oracle.OracleConnector;
 import org.dbsyncer.connector.postgresql.PostgreSQLConnector;
 import org.dbsyncer.connector.sql.DQLMysqlConnector;
 import org.dbsyncer.connector.sql.DQLOracleConnector;
+import org.dbsyncer.connector.sql.DQLPostgreSQLConnector;
 import org.dbsyncer.connector.sql.DQLSqlServerConnector;
 import org.dbsyncer.connector.sqlserver.SqlServerConnector;
 
@@ -40,7 +41,7 @@ public enum ConnectorEnum {
     /**
      * PostgreSQL 连接器
      */
-    PostgreSQL("PostgreSQL", new PostgreSQLConnector(), DatabaseConfig.class),
+    POSTGRE_SQL("PostgreSQL", new PostgreSQLConnector(), DatabaseConfig.class),
     /**
      * Elasticsearch 连接器
      */
@@ -60,7 +61,11 @@ public enum ConnectorEnum {
     /**
      * DqlSqlServer 连接器
      */
-    DQL_SQL_SERVER("DqlSqlServer", new DQLSqlServerConnector(), DatabaseConfig.class);
+    DQL_SQL_SERVER("DqlSqlServer", new DQLSqlServerConnector(), DatabaseConfig.class),
+    /**
+     * DqlPostgreSQL 连接器
+     */
+    DQL_POSTGRE_SQL("DqlPostgreSQL", new DQLPostgreSQLConnector(), DatabaseConfig.class);
 
     // 连接器名称
     private String type;

+ 88 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/AbstractDQLConnector.java

@@ -0,0 +1,88 @@
+package org.dbsyncer.connector.sql;
+
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.connector.ConnectorException;
+import org.dbsyncer.connector.config.*;
+import org.dbsyncer.connector.constant.ConnectorConstant;
+import org.dbsyncer.connector.database.AbstractDatabaseConnector;
+import org.dbsyncer.connector.database.DatabaseConnectorMapper;
+import org.dbsyncer.connector.enums.SqlBuilderEnum;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/4/6 22:16
+ */
+public abstract class AbstractDQLConnector extends AbstractDatabaseConnector {
+
+    @Override
+    protected String getTableSql(DatabaseConfig config) {
+        throw new ConnectorException("Unsupported method.");
+    }
+
+    @Override
+    public List<Table> getTable(DatabaseConnectorMapper config) {
+        DatabaseConfig cfg = config.getConfig();
+        List<Table> tables = new ArrayList<>();
+        tables.add(new Table(cfg.getSql()));
+        return tables;
+    }
+
+    @Override
+    public Map<String, String> getSourceCommand(CommandConfig commandConfig) {
+        return getDqlSourceCommand(commandConfig, false);
+    }
+
+    @Override
+    public MetaInfo getMetaInfo(DatabaseConnectorMapper connectorMapper, String tableName) {
+        DatabaseConfig cfg = connectorMapper.getConfig();
+        String sql = cfg.getSql().toUpperCase();
+        String queryMetaSql = StringUtil.contains(sql, " WHERE ") ? sql + " AND 1!=1 " : sql + " WHERE 1!=1 ";
+        return connectorMapper.execute(databaseTemplate -> super.getMetaInfo(databaseTemplate, queryMetaSql, cfg.getTable()));
+    }
+
+    /**
+     * 获取DQL源配置
+     *
+     * @param commandConfig
+     * @param appendGroupByPK
+     * @return
+     */
+    protected Map<String, String> getDqlSourceCommand(CommandConfig commandConfig, boolean appendGroupByPK) {
+        // 获取过滤SQL
+        List<Filter> filter = commandConfig.getFilter();
+        String queryFilterSql = getQueryFilterSql(filter);
+
+        // 获取查询SQL
+        Table table = commandConfig.getTable();
+        Map<String, String> map = new HashMap<>();
+        String querySql = table.getName();
+
+        // 存在条件
+        if (StringUtil.isNotBlank(queryFilterSql)) {
+            querySql += queryFilterSql;
+        }
+        String quotation = buildSqlWithQuotation();
+        String pk = findTablePrimaryKey(commandConfig.getOriginalTable(), quotation);
+        map.put(SqlBuilderEnum.QUERY.getName(), getPageSql(new PageSqlConfig(querySql, pk)));
+
+        // 获取查询总数SQL
+        StringBuilder queryCount = new StringBuilder();
+        queryCount.append("SELECT COUNT(1) FROM (").append(table.getName());
+        if (StringUtil.isNotBlank(queryFilterSql)) {
+            queryCount.append(queryFilterSql);
+        }
+        // Mysql
+        if (appendGroupByPK) {
+            queryCount.append(" GROUP BY ").append(pk);
+        }
+        queryCount.append(") DBSYNCER_T");
+        map.put(ConnectorConstant.OPERTION_QUERY_COUNT, queryCount.toString());
+        return map;
+    }
+}

+ 3 - 20
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLMysqlConnector.java

@@ -1,19 +1,12 @@
 package org.dbsyncer.connector.sql;
 
-import org.dbsyncer.connector.config.*;
+import org.dbsyncer.connector.config.CommandConfig;
+import org.dbsyncer.connector.config.PageSqlConfig;
 import org.dbsyncer.connector.constant.DatabaseConstant;
-import org.dbsyncer.connector.database.AbstractDatabaseConnector;
-import org.dbsyncer.connector.database.DatabaseConnectorMapper;
 
-import java.util.List;
 import java.util.Map;
 
-public final class DQLMysqlConnector extends AbstractDatabaseConnector {
-
-    @Override
-    protected String getTableSql(DatabaseConfig config) {
-        return "show tables";
-    }
+public final class DQLMysqlConnector extends AbstractDQLConnector {
 
     @Override
     public String getPageSql(PageSqlConfig config) {
@@ -25,16 +18,6 @@ public final class DQLMysqlConnector extends AbstractDatabaseConnector {
         return new Object[]{(pageIndex - 1) * pageSize, pageSize};
     }
 
-    @Override
-    public List<Table> getTable(DatabaseConnectorMapper config) {
-        return super.getDqlTable(config);
-    }
-
-    @Override
-    public MetaInfo getMetaInfo(DatabaseConnectorMapper connectorMapper, String tableName) {
-        return super.getDqlMetaInfo(connectorMapper);
-    }
-
     @Override
     public Map<String, String> getSourceCommand(CommandConfig commandConfig) {
         return super.getDqlSourceCommand(commandConfig, true);

+ 3 - 28
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLOracleConnector.java

@@ -1,19 +1,9 @@
 package org.dbsyncer.connector.sql;
 
-import org.dbsyncer.connector.config.*;
+import org.dbsyncer.connector.config.PageSqlConfig;
 import org.dbsyncer.connector.constant.DatabaseConstant;
-import org.dbsyncer.connector.database.AbstractDatabaseConnector;
-import org.dbsyncer.connector.database.DatabaseConnectorMapper;
 
-import java.util.List;
-import java.util.Map;
-
-public final class DQLOracleConnector extends AbstractDatabaseConnector {
-
-    @Override
-    protected String getTableSql(DatabaseConfig config) {
-        return "SELECT TABLE_NAME,TABLE_TYPE FROM USER_TAB_COMMENTS";
-    }
+public final class DQLOracleConnector extends AbstractDQLConnector {
 
     @Override
     public String getPageSql(PageSqlConfig config) {
@@ -22,22 +12,7 @@ public final class DQLOracleConnector extends AbstractDatabaseConnector {
 
     @Override
     public Object[] getPageArgs(int pageIndex, int pageSize) {
-        return new Object[] {pageIndex * pageSize, (pageIndex - 1) * pageSize};
-    }
-
-    @Override
-    public List<Table> getTable(DatabaseConnectorMapper config) {
-        return super.getDqlTable(config);
-    }
-
-    @Override
-    public MetaInfo getMetaInfo(DatabaseConnectorMapper connectorMapper, String tableName) {
-        return super.getDqlMetaInfo(connectorMapper);
-    }
-
-    @Override
-    public Map<String, String> getSourceCommand(CommandConfig commandConfig) {
-        return super.getDqlSourceCommand(commandConfig, false);
+        return new Object[]{pageIndex * pageSize, (pageIndex - 1) * pageSize};
     }
 
     @Override

+ 22 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLPostgreSQLConnector.java

@@ -0,0 +1,22 @@
+package org.dbsyncer.connector.sql;
+
+import org.dbsyncer.connector.config.PageSqlConfig;
+import org.dbsyncer.connector.constant.DatabaseConstant;
+
+public final class DQLPostgreSQLConnector extends AbstractDQLConnector {
+
+    @Override
+    public String getPageSql(PageSqlConfig config) {
+        return config.getQuerySql() + DatabaseConstant.POSTGRESQL_PAGE_SQL;
+    }
+
+    @Override
+    public Object[] getPageArgs(int pageIndex, int pageSize) {
+        return new Object[]{pageSize, (pageIndex - 1) * pageSize};
+    }
+
+    @Override
+    protected String buildSqlWithQuotation() {
+        return "\"";
+    }
+}

+ 3 - 27
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLSqlServerConnector.java

@@ -3,18 +3,14 @@ package org.dbsyncer.connector.sql;
 import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.connector.ConnectorMapper;
-import org.dbsyncer.connector.config.*;
+import org.dbsyncer.connector.config.DatabaseConfig;
+import org.dbsyncer.connector.config.PageSqlConfig;
 import org.dbsyncer.connector.constant.DatabaseConstant;
-import org.dbsyncer.connector.database.AbstractDatabaseConnector;
-import org.dbsyncer.connector.database.DatabaseConnectorMapper;
 import org.dbsyncer.connector.sqlserver.SqlServerConnectorMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.List;
-import java.util.Map;
-
-public final class DQLSqlServerConnector extends AbstractDatabaseConnector {
+public final class DQLSqlServerConnector extends AbstractDQLConnector {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
@@ -28,11 +24,6 @@ public final class DQLSqlServerConnector extends AbstractDatabaseConnector {
         }
     }
 
-    @Override
-    protected String getTableSql(DatabaseConfig config) {
-        return String.format("SELECT NAME FROM SYS.TABLES WHERE SCHEMA_ID = SCHEMA_ID('%s')", config.getSchema());
-    }
-
     @Override
     public String getPageSql(PageSqlConfig config) {
         if (StringUtil.isBlank(config.getPk())) {
@@ -47,19 +38,4 @@ public final class DQLSqlServerConnector extends AbstractDatabaseConnector {
         return new Object[]{(pageIndex - 1) * pageSize + 1, pageIndex * pageSize};
     }
 
-    @Override
-    public List<Table> getTable(DatabaseConnectorMapper config) {
-        return super.getDqlTable(config);
-    }
-
-    @Override
-    public MetaInfo getMetaInfo(DatabaseConnectorMapper connectorMapper, String tableName) {
-        return super.getDqlMetaInfo(connectorMapper);
-    }
-
-    @Override
-    public Map<String, String> getSourceCommand(CommandConfig commandConfig) {
-        return super.getDqlSourceCommand(commandConfig, false);
-    }
-
 }

+ 62 - 0
dbsyncer-web/src/main/resources/public/connector/addDqlPostgreSQL.html

@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="zh-CN"
+      xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
+
+<div th:fragment="content">
+    <div class="form-group">
+        <label class="col-sm-2 control-label">帐号 <strong class="driverVerifcateRequired">*</strong></label>
+        <div class="col-sm-4">
+            <input class="form-control" dbsyncer-valid="require" maxlength="32" name="username" placeholder="admin"
+                   th:value="${connector?.config?.username}" type="text"/>
+        </div>
+        <label class="col-sm-2 control-label">密码 <strong class="driverVerifcateRequired">*</strong></label>
+        <div class="col-sm-4 ">
+            <input class="form-control" dbsyncer-valid="require" maxlength="32" name="password"
+                   th:value="${connector?.config?.password}" type="password"/>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="col-sm-2 control-label">SQL <strong class="driverVerifcateRequired">*</strong></label>
+        <div class="col-sm-10">
+            <textarea class="form-control dbsyncer_textarea_resize_none" dbsyncer-valid="require" id="sql"
+                      maxlength="1024" name="sql" rows="10"
+                      th:text="${connector?.config?.sql}?:'SELECT T1.* FROM &quot;USER&quot; T1'"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="col-sm-2 control-label">主表 <strong class="driverVerifcateRequired">*</strong></label>
+        <div class="col-sm-4">
+            <input class="form-control" dbsyncer-valid="require" maxlength="32" name="table" placeholder="USER"
+                   th:value="${connector?.config?.table}" type="text"/>
+        </div>
+        <div class="col-sm-6 text-right">
+            <a href="javascript:beautifySql();"><span class="fa fa-magic fa-1x fa-flip-horizontal dbsyncer_pointer"
+                                                      title="美化SQL"></span>美化SQL</a>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="col-sm-2 control-label">URL <strong class="driverVerifcateRequired">*</strong></label>
+        <div class="col-sm-10">
+            <textarea class="form-control dbsyncer_textarea_resize_none" dbsyncer-valid="require" maxlength="1024"
+                      name="url" rows="5"
+                      th:text="${connector?.config?.url} ?: 'jdbc:postgresql://127.0.0.1:5432/test'"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="col-sm-2 control-label">架构名 <strong class="driverVerifcateRequired">*</strong></label>
+        <div class="col-sm-4">
+            <input class="form-control" dbsyncer-valid="require" maxlength="32" name="schema" placeholder="public"
+                   th:value="${connector?.config?.schema} ?: 'public'" type="text"/>
+        </div>
+        <div class="col-sm-6"></div>
+    </div>
+    <div class="form-group">
+        <label class="col-sm-2 control-label">驱动 </label>
+        <div class="col-sm-10">
+            <input class="form-control" name="driverClassName" readonly="true"
+                   th:value="${connector?.config?.driverClassName} ?: 'org.postgresql.Driver'" type="text"/>
+        </div>
+    </div>
+</div>
+
+</html>

+ 1 - 1
dbsyncer-web/src/main/resources/public/connector/addPostgreSQL.html

@@ -26,7 +26,7 @@
     <div class="form-group">
         <label class="col-sm-2 control-label">架构名 <strong class="driverVerifcateRequired">*</strong></label>
         <div class="col-sm-4">
-            <input class="form-control" dbsyncer-valid="require" maxlength="32" name="schema" placeholder="dbo"
+            <input class="form-control" dbsyncer-valid="require" maxlength="32" name="schema" placeholder="public"
                    th:value="${connector?.config?.schema} ?: 'public'" type="text"/>
         </div>
         <div class="col-sm-6"></div>