88import ai .chat2db .spi .SqlBuilder ;
99import ai .chat2db .spi .jdbc .DefaultMetaService ;
1010import ai .chat2db .spi .model .*;
11+ import ai .chat2db .spi .sql .Chat2DBContext ;
1112import ai .chat2db .spi .sql .SQLExecutor ;
1213import ai .chat2db .spi .util .SortUtils ;
1314import com .google .common .collect .Lists ;
1415import jakarta .validation .constraints .NotEmpty ;
16+ import lombok .extern .slf4j .Slf4j ;
17+ import org .apache .commons .collections4 .CollectionUtils ;
1518import org .apache .commons .lang3 .StringUtils ;
1619
1720import java .sql .Connection ;
2023import java .util .*;
2124import java .util .stream .Collectors ;
2225
26+ @ Slf4j
2327public class DMMetaData extends DefaultMetaService implements MetaData {
2428
25- private List <String > systemSchemas = Arrays .asList ("CTISYS" , "SYS" ,"SYSDBA" ,"SYSSSO" ,"SYSAUDITOR" );
29+ private List <String > systemSchemas = Arrays .asList ("CTISYS" , "SYS" , "SYSDBA" , "SYSSSO" , "SYSAUDITOR" );
2630
2731 @ Override
2832 public List <Schema > schemas (Connection connection , String databaseName ) {
2933 List <Schema > schemas = SQLExecutor .getInstance ().schemas (connection , databaseName , null );
3034 return SortUtils .sortSchema (schemas , systemSchemas );
3135 }
32- private String format (String tableName ){
36+
37+ private String format (String tableName ) {
3338 return "\" " + tableName + "\" " ;
34- }
39+ }
3540
3641 private static String tableDDL = "SELECT dbms_metadata.get_ddl('TABLE', '%s','%s') as ddl FROM dual ;" ;
37- private static String tableComment = "select COMMENTS from dba_tab_comments where OWNER='%s' and TABLE_TYPE='TABLE' and TABLE_NAME='%s';" ;
38- private static String columnComment = "SELECT COLNAME,COMMENT$ FROM SYS.SYSCOLUMNCOMMENTS where SCHNAME = '%s' and TVNAME = '%s' and TABLE_TYPE = 'TABLE';" ;
3942
40- public String tableDDL (Connection connection , String databaseName , String schemaName , String tableName ) {
43+ public String tableDDL (Connection connection , String databaseName , String schemaName , String tableName ) {
4144 String tableDDLSql = String .format (tableDDL , tableName , schemaName );
42- String tableCommentSql = String .format (tableComment , schemaName , tableName );
43- String columnCommentSql = String .format (columnComment , schemaName , tableName );
4445 StringBuilder ddlBuilder = new StringBuilder ();
4546 SQLExecutor .getInstance ().execute (connection , tableDDLSql , resultSet -> {
4647 if (resultSet .next ()) {
4748 String ddl = resultSet .getString ("ddl" );
4849 ddlBuilder .append (ddl ).append ("\n " );
4950 }
5051 });
51- SQLExecutor .getInstance ().execute (connection , tableCommentSql , resultSet -> {
52- if (resultSet .next ()) {
53- String comments = resultSet .getString ("COMMENTS" );
54- if (Objects .nonNull (comments )) {
55- ddlBuilder .append ("COMMENT ON TABLE " ).append (format (schemaName )).append ("." ).append (format (tableName ))
56- .append (" IS " ).append (comments ).append (";" ).append ("\n " );
52+ MetaData metaData = Chat2DBContext .getMetaData ();
53+ List <Table > tables = metaData .tables (connection , databaseName , schemaName , tableName );
54+ if (CollectionUtils .isNotEmpty (tables )) {
55+ String tableComment = tables .get (0 ).getComment ();
56+ if (StringUtils .isNotBlank (tableComment )) {
57+ ddlBuilder .append ("COMMENT ON TABLE " ).append (format (schemaName )).append ("." ).append (format (tableName ))
58+ .append (" IS '" ).append (tableComment .replace ("'" , "''" )).append ("'" ).append (";" ).append ("\n " );
59+ }
60+ }
61+ List <TableColumn > columns = metaData .columns (connection , databaseName , schemaName , tableName );
62+ if (CollectionUtils .isNotEmpty (columns )) {
63+ for (TableColumn column : columns ) {
64+ String columnName = column .getName ();
65+ String comment = column .getComment ();
66+ if (StringUtils .isNotBlank (comment )) {
67+ ddlBuilder .append ("COMMENT ON COLUMN " ).append (format (schemaName )).append ("." ).append (format (tableName ))
68+ .append ("." ).append (format (columnName )).append (" IS " )
69+ .append ("'" ).append (comment .replace ("'" , "''" ))
70+ .append ("';" ).append ("\n " );
5771 }
5872 }
59- });
60- SQLExecutor .getInstance ().execute (connection , columnCommentSql , resultSet -> {
61- while (resultSet .next ()) {
62- String columnName = resultSet .getString ("COLNAME" );
63- String comment = resultSet .getString ("COMMENT$" );
64- ddlBuilder .append ("COMMENT ON COLUMN " ).append (format (schemaName )).append ("." ).append (format (tableName ))
65- .append ("." ).append (format (columnName )).append (" IS " ).append ("'" ).append (comment ).append ("';" ).append ("\n " );
73+ }
74+ if (tableName .startsWith ("V$" )){
75+ return ddlBuilder .toString ();
76+ }
77+ List <TableIndex > indexes = metaData .indexes (connection , databaseName , schemaName , tableName );
78+ if (CollectionUtils .isNotEmpty (indexes )) {
79+ for (TableIndex index : indexes ) {
80+ String indexName = index .getName ();
81+ if (StringUtils .isNotBlank (indexName )) {
82+ String sql = "select DBMS_METADATA.GET_DDL('INDEX','%s') as INDEX_DDL" ;
83+ try {
84+ SQLExecutor .getInstance ().execute (connection , String .format (sql ,indexName ), resultSet -> {
85+ if (resultSet .next ()) {
86+ ddlBuilder .append (resultSet .getString ("INDEX_DDL" )).append ("\n " );
87+ }
88+ });
89+ } catch (Exception e ) {
90+ log .warn ("Failed to get the DDL of the index." );
91+ for (TableIndex tableIndex : indexes ) {
92+ DMIndexTypeEnum indexTypeEnum = DMIndexTypeEnum .getByType (tableIndex .getType ());
93+ ddlBuilder .append ("\n " ).append (indexTypeEnum .buildIndexScript (tableIndex )).append (";" );
94+ }
95+ }
96+ }
6697 }
67- });
98+ }
6899 return ddlBuilder .toString ();
69100 }
70101
71102 private static String ROUTINES_SQL
72- = "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND OWNER = '%s' AND NAME = '%s' ORDER BY LINE" ;
103+ = "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND OWNER = '%s' AND NAME = '%s' ORDER BY LINE" ;
73104
74105 @ Override
75106 public Function function (Connection connection , @ NotEmpty String databaseName , String schemaName ,
76- String functionName ) {
107+ String functionName ) {
77108
78- String sql = String .format (ROUTINES_SQL , "PROC" ,schemaName , functionName );
109+ String sql = String .format (ROUTINES_SQL , "PROC" , schemaName , functionName );
79110 return SQLExecutor .getInstance ().execute (connection , sql , resultSet -> {
80111 StringBuilder sb = new StringBuilder ();
81112 while (resultSet .next ()) {
@@ -94,8 +125,8 @@ public Function function(Connection connection, @NotEmpty String databaseName, S
94125
95126 @ Override
96127 public Procedure procedure (Connection connection , @ NotEmpty String databaseName , String schemaName ,
97- String procedureName ) {
98- String sql = String .format (ROUTINES_SQL , "PROC" , schemaName ,procedureName );
128+ String procedureName ) {
129+ String sql = String .format (ROUTINES_SQL , "PROC" , schemaName , procedureName );
99130 return SQLExecutor .getInstance ().execute (connection , sql , resultSet -> {
100131 StringBuilder sb = new StringBuilder ();
101132 while (resultSet .next ()) {
@@ -111,8 +142,8 @@ public Procedure procedure(Connection connection, @NotEmpty String databaseName,
111142 }
112143
113144 private static String TRIGGER_SQL
114- = "SELECT OWNER, TRIGGER_NAME, TABLE_OWNER, TABLE_NAME, TRIGGERING_TYPE, TRIGGERING_EVENT, STATUS, TRIGGER_BODY "
115- + "FROM ALL_TRIGGERS WHERE OWNER = '%s' AND TRIGGER_NAME = '%s'" ;
145+ = "SELECT OWNER, TRIGGER_NAME, TABLE_OWNER, TABLE_NAME, TRIGGERING_TYPE, TRIGGERING_EVENT, STATUS, TRIGGER_BODY "
146+ + "FROM ALL_TRIGGERS WHERE OWNER = '%s' AND TRIGGER_NAME = '%s'" ;
116147
117148 private static String TRIGGER_SQL_LIST = "SELECT OWNER, TRIGGER_NAME FROM ALL_TRIGGERS WHERE OWNER = '%s'" ;
118149
@@ -134,7 +165,7 @@ public List<Trigger> triggers(Connection connection, String databaseName, String
134165
135166 @ Override
136167 public Trigger trigger (Connection connection , @ NotEmpty String databaseName , String schemaName ,
137- String triggerName ) {
168+ String triggerName ) {
138169
139170 String sql = String .format (TRIGGER_SQL , schemaName , triggerName );
140171 return SQLExecutor .getInstance ().execute (connection , sql , resultSet -> {
@@ -150,7 +181,7 @@ public Trigger trigger(Connection connection, @NotEmpty String databaseName, Str
150181 }
151182
152183 private static String VIEW_SQL
153- = "SELECT OWNER, VIEW_NAME, TEXT FROM ALL_VIEWS WHERE OWNER = '%s' AND VIEW_NAME = '%s'" ;
184+ = "SELECT OWNER, VIEW_NAME, TEXT FROM ALL_VIEWS WHERE OWNER = '%s' AND VIEW_NAME = '%s'" ;
154185
155186 @ Override
156187 public Table view (Connection connection , String databaseName , String schemaName , String viewName ) {
0 commit comments