feat: rewrite sqlserver meta provider
This commit is contained in:
parent
bab82d43df
commit
66ee6405e2
|
@ -2,6 +2,9 @@ package com.databasir.core.meta.provider;
|
|||
|
||||
import com.databasir.core.meta.provider.jdbc.*;
|
||||
import com.databasir.core.meta.provider.mysql.MysqlTableTriggerMetaProvider;
|
||||
import com.databasir.core.meta.provider.sqlserver.SqlServerColumnMetaProvider;
|
||||
import com.databasir.core.meta.provider.sqlserver.SqlServerTableMetaProvider;
|
||||
import com.databasir.core.meta.provider.sqlserver.SqlServerTriggerMetaProvider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
@ -35,7 +38,7 @@ public class MetaProviders {
|
|||
return jdbc();
|
||||
}
|
||||
if (url.contains(":sqlserver:")) {
|
||||
return jdbc();
|
||||
return sqlServer();
|
||||
}
|
||||
if (url.contains(":mysql:")) {
|
||||
return mysql();
|
||||
|
@ -57,4 +60,17 @@ public class MetaProviders {
|
|||
return new JdbcDatabaseMetaProvider(tableMetaProvider);
|
||||
}
|
||||
|
||||
private static DatabaseMetaProvider sqlServer() {
|
||||
var columnMetaProvider = new SqlServerColumnMetaProvider();
|
||||
var foreignKeyMetaProvider = new JdbcForeignKeyMetaProvider();
|
||||
var indexMetaProvider = new JdbcIndexMetaProvider();
|
||||
var triggerMetaProvider = new SqlServerTriggerMetaProvider();
|
||||
var tableMetaProvider = new SqlServerTableMetaProvider(
|
||||
columnMetaProvider,
|
||||
indexMetaProvider,
|
||||
foreignKeyMetaProvider,
|
||||
triggerMetaProvider
|
||||
);
|
||||
return new JdbcDatabaseMetaProvider(tableMetaProvider);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ public class MysqlTableTriggerMetaProvider implements TriggerMetaProvider {
|
|||
}
|
||||
return triggers;
|
||||
} catch (SQLException e) {
|
||||
log.warn("create trigger doc failed", e);
|
||||
log.warn("get trigger meta failed", e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package com.databasir.core.meta.provider.sqlserver;
|
||||
|
||||
import com.databasir.core.meta.data.ColumnMeta;
|
||||
import com.databasir.core.meta.provider.ColumnMetaProvider;
|
||||
import com.databasir.core.meta.provider.condition.TableCondition;
|
||||
import com.databasir.core.meta.provider.jdbc.JdbcColumnMetaProvider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class SqlServerColumnMetaProvider implements ColumnMetaProvider {
|
||||
|
||||
private final ColumnMetaProvider columnMetaProvider = new JdbcColumnMetaProvider();
|
||||
|
||||
@Override
|
||||
public List<ColumnMeta> selectColumns(Connection connection, TableCondition condition) {
|
||||
Map<String, String> columnRemarksMap = getColumnRemarks(connection, condition);
|
||||
return columnMetaProvider.selectColumns(connection, condition)
|
||||
.stream()
|
||||
.map(column -> {
|
||||
String remark = columnRemarksMap.getOrDefault(column.getName(), "");
|
||||
column.setComment(remark);
|
||||
return column;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Map<String, String> getColumnRemarks(Connection connection,
|
||||
TableCondition condition) {
|
||||
String sql = "SELECT col.name AS COLUMN_NAME,\n" +
|
||||
" ep.value AS REMARKS\n" +
|
||||
"FROM sys.tables AS tab\n" +
|
||||
" INNER JOIN sys.columns AS col\n" +
|
||||
" ON tab.object_id = col.object_id\n" +
|
||||
" LEFT JOIN sys.extended_properties AS ep " +
|
||||
"ON ep.major_id = col.object_id AND ep.minor_id = col.column_id\n" +
|
||||
"WHERE tab.name LIKE ?\n" +
|
||||
" AND SCHEMA_NAME(tab.schema_id) LIKE ?\n" +
|
||||
"ORDER BY tab.name, column_id;";
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
PreparedStatement preparedStatement = null;
|
||||
try {
|
||||
preparedStatement = connection.prepareStatement(sql);
|
||||
preparedStatement.setString(1, condition.getTableName());
|
||||
preparedStatement.setString(2, condition.getSchemaName());
|
||||
ResultSet result = preparedStatement.executeQuery();
|
||||
while (result.next()) {
|
||||
String name = result.getString("COLUMN_NAME");
|
||||
String remarks = result.getString("REMARKS");
|
||||
if (name == null || remarks == null) {
|
||||
continue;
|
||||
} else {
|
||||
map.put(name, remarks);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("", e);
|
||||
} finally {
|
||||
if (preparedStatement != null) {
|
||||
try {
|
||||
preparedStatement.close();
|
||||
} catch (SQLException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package com.databasir.core.meta.provider.sqlserver;
|
||||
|
||||
import com.databasir.core.meta.data.ColumnMeta;
|
||||
import com.databasir.core.meta.data.TableMeta;
|
||||
import com.databasir.core.meta.provider.*;
|
||||
import com.databasir.core.meta.provider.condition.Condition;
|
||||
import com.databasir.core.meta.provider.condition.TableCondition;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class SqlServerTableMetaProvider implements TableMetaProvider {
|
||||
|
||||
private final ColumnMetaProvider columnMetaProvider;
|
||||
|
||||
private final IndexMetaProvider indexMetaProvider;
|
||||
|
||||
private final ForeignKeyMetaProvider foreignKeyMetaProvider;
|
||||
|
||||
private final TriggerMetaProvider triggerMetaProvider;
|
||||
|
||||
@Override
|
||||
public List<TableMeta> selectTables(Connection connection, Condition condition) {
|
||||
String sql = "SELECT sys.objects.name AS TABLE_NAME,\n" +
|
||||
" sys.objects.type_desc AS TABLE_TYPE,\n" +
|
||||
" CAST(extended_properties.value AS NVARCHAR(500)) AS REMARKS\n" +
|
||||
"FROM sys.objects\n" +
|
||||
" LEFT JOIN sys.schemas ON sys.objects.schema_id = sys.schemas.schema_id\n" +
|
||||
" LEFT JOIN sys.extended_properties " +
|
||||
"ON sys.objects.object_id = sys.extended_properties.major_id\n" +
|
||||
"WHERE (type = 'U' OR type = 'V')\n" +
|
||||
" AND sys.extended_properties.minor_id = 0\n" +
|
||||
" AND sys.schemas.name LIKE ?;\n";
|
||||
PreparedStatement preparedStatement = null;
|
||||
try {
|
||||
preparedStatement = connection.prepareStatement(sql);
|
||||
preparedStatement.setString(1, condition.getSchemaName());
|
||||
ResultSet results = preparedStatement.executeQuery();
|
||||
return doSelect(results, connection, condition);
|
||||
} catch (SQLException e) {
|
||||
log.warn("get table meta failed {}", e.getMessage());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("get table meta failed", e);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
} finally {
|
||||
if (preparedStatement != null) {
|
||||
try {
|
||||
preparedStatement.close();
|
||||
} catch (SQLException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<TableMeta> doSelect(ResultSet tablesResult,
|
||||
Connection connection,
|
||||
Condition condition) throws SQLException {
|
||||
List<TableMeta> tableMetas = new ArrayList<>();
|
||||
try {
|
||||
while (tablesResult.next()) {
|
||||
String tableName = tablesResult.getString("TABLE_NAME");
|
||||
if (condition.tableIsIgnored(tableName)) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("ignored table: " + condition.getSchemaName() + "." + tableName);
|
||||
}
|
||||
} else {
|
||||
String tableType = tablesResult.getString("TABLE_TYPE");
|
||||
String tableComment = tablesResult.getString("REMARKS");
|
||||
TableCondition tableCondition = TableCondition.of(condition, tableName);
|
||||
List<ColumnMeta> columns = columnMetaProvider.selectColumns(connection, tableCondition);
|
||||
if (columns.isEmpty()) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("ignored table: " + condition.getSchemaName() + "." + tableName
|
||||
+ ", caused by get empty columns");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
TableMeta tableMeta = TableMeta.builder()
|
||||
.name(tableName)
|
||||
.type(tableType)
|
||||
.comment(tableComment)
|
||||
.columns(columns)
|
||||
.foreignKeys(foreignKeyMetaProvider.selectForeignKeys(connection, tableCondition))
|
||||
.indexes(indexMetaProvider.selectIndexes(connection, tableCondition))
|
||||
.triggers(triggerMetaProvider.selectTriggers(connection, tableCondition))
|
||||
.build();
|
||||
tableMetas.add(tableMeta);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
tablesResult.close();
|
||||
}
|
||||
return tableMetas;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package com.databasir.core.meta.provider.sqlserver;
|
||||
|
||||
import com.databasir.core.meta.data.TriggerMeta;
|
||||
import com.databasir.core.meta.provider.TriggerMetaProvider;
|
||||
import com.databasir.core.meta.provider.condition.TableCondition;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Slf4j
|
||||
public class SqlServerTriggerMetaProvider implements TriggerMetaProvider {
|
||||
|
||||
private static final Pattern DATE_TIME_PATTERN =
|
||||
Pattern.compile("(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})(.*)");
|
||||
|
||||
@Override
|
||||
public List<TriggerMeta> selectTriggers(Connection connection, TableCondition condition) {
|
||||
String sql = "SELECT SCHEMA_NAME(tab.schema_id) + '.' + tab.name AS table_name,\n" +
|
||||
" trig.name AS trigger_name,\n" +
|
||||
" trig.create_date AS create_date,\n" +
|
||||
" CASE\n" +
|
||||
" WHEN is_instead_of_trigger = 1 THEN 'Instead of'\n" +
|
||||
" ELSE 'After' END AS timing,\n" +
|
||||
" (CASE\n" +
|
||||
" WHEN OBJECTPROPERTY(trig.object_id, 'ExecIsUpdateTrigger') = 1\n" +
|
||||
" THEN 'Update '\n" +
|
||||
" ELSE '' END\n" +
|
||||
" + CASE\n" +
|
||||
" WHEN OBJECTPROPERTY(trig.object_id, 'ExecIsDeleteTrigger') = 1\n" +
|
||||
" THEN 'Delete '\n" +
|
||||
" ELSE '' END\n" +
|
||||
" + CASE\n" +
|
||||
" WHEN OBJECTPROPERTY(trig.object_id, 'ExecIsInsertTrigger') = 1\n" +
|
||||
" THEN 'Insert '\n" +
|
||||
" ELSE '' END\n" +
|
||||
" ) AS manipulation,\n" +
|
||||
" CASE\n" +
|
||||
" WHEN trig.[type] = 'TA' THEN 'Assembly (CLR) trigger'\n" +
|
||||
" WHEN trig.[type] = 'TR' THEN 'SQL trigger'\n" +
|
||||
" ELSE '' END AS [TYPE],\n" +
|
||||
" CASE\n" +
|
||||
" WHEN is_disabled = 1 THEN 'Disabled'\n" +
|
||||
" ELSE 'Active' END AS [status],\n" +
|
||||
" OBJECT_DEFINITION(trig.object_id) AS STATEMENT\n" +
|
||||
"FROM sys.triggers trig\n" +
|
||||
" INNER JOIN sys.objects tab\n" +
|
||||
" ON trig.parent_id = tab.object_id\n" +
|
||||
"WHERE SCHEMA_NAME(tab.schema_id) = ? AND tab.name = ?";
|
||||
PreparedStatement preparedStatement = null;
|
||||
List<TriggerMeta> triggerMetas = new ArrayList<>();
|
||||
try {
|
||||
preparedStatement = connection.prepareStatement(sql);
|
||||
preparedStatement.setString(1, condition.getSchemaName());
|
||||
preparedStatement.setString(2, condition.getTableName());
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
while (resultSet.next()) {
|
||||
String triggerName = resultSet.getString("trigger_name");
|
||||
String timing = resultSet.getString("timing");
|
||||
String manipulation = resultSet.getString("manipulation");
|
||||
String statement = resultSet.getString("statement");
|
||||
Matcher matcher = DATE_TIME_PATTERN.matcher(resultSet.getString("create_date"));
|
||||
String createAt;
|
||||
if (matcher.matches()) {
|
||||
createAt = matcher.group(1);
|
||||
} else {
|
||||
createAt = "1970-01-01 00:00:00";
|
||||
}
|
||||
triggerMetas.add(TriggerMeta.builder()
|
||||
.name(triggerName)
|
||||
.timing(timing)
|
||||
.manipulation(manipulation)
|
||||
.statement(statement)
|
||||
.createAt(createAt)
|
||||
.build());
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.warn("ignore trigger meta by error {}", e.getMessage());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("ignore trigger meta by error ", e);
|
||||
}
|
||||
} finally {
|
||||
if (preparedStatement != null) {
|
||||
try {
|
||||
preparedStatement.close();
|
||||
} catch (SQLException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return triggerMetas;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue