mirror of
				https://github.com/vran-dev/databasir.git
				synced 2025-11-04 16:26:10 +08:00 
			
		
		
		
	feat: support mysql trigger
This commit is contained in:
		@@ -1,20 +0,0 @@
 | 
				
			|||||||
package com.databasir.core.doc.factory.extension;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.databasir.core.doc.factory.DatabaseDocConfiguration;
 | 
					 | 
				
			||||||
import com.databasir.core.doc.factory.TableTriggerDocFactory;
 | 
					 | 
				
			||||||
import com.databasir.core.doc.model.TriggerDoc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.sql.DatabaseMetaData;
 | 
					 | 
				
			||||||
import java.util.Collections;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class MysqlTableTriggerDocFactory implements TableTriggerDocFactory {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public List<TriggerDoc> create(String tableName,
 | 
					 | 
				
			||||||
                                   DatabaseMetaData metaData,
 | 
					 | 
				
			||||||
                                   DatabaseDocConfiguration configuration) {
 | 
					 | 
				
			||||||
        return Collections.emptyList();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					package com.databasir.core.doc.factory.extension.mysql;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.databasir.core.doc.factory.DatabaseDocConfiguration;
 | 
				
			||||||
 | 
					import com.databasir.core.doc.factory.TableTriggerDocFactory;
 | 
				
			||||||
 | 
					import com.databasir.core.doc.model.TriggerDoc;
 | 
				
			||||||
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.sql.DatabaseMetaData;
 | 
				
			||||||
 | 
					import java.sql.PreparedStatement;
 | 
				
			||||||
 | 
					import java.sql.ResultSet;
 | 
				
			||||||
 | 
					import java.sql.SQLException;
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.Collections;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Slf4j
 | 
				
			||||||
 | 
					public class MysqlTableTriggerDocFactory implements TableTriggerDocFactory {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public List<TriggerDoc> create(String tableName,
 | 
				
			||||||
 | 
					                                   DatabaseMetaData metaData,
 | 
				
			||||||
 | 
					                                   DatabaseDocConfiguration configuration) {
 | 
				
			||||||
 | 
					        String sql = "SELECT TRIGGER_CATALOG,\n" +
 | 
				
			||||||
 | 
					                "       TRIGGER_SCHEMA,\n" +
 | 
				
			||||||
 | 
					                "       TRIGGER_NAME,\n" +
 | 
				
			||||||
 | 
					                "       EVENT_MANIPULATION,\n" +
 | 
				
			||||||
 | 
					                "       EVENT_OBJECT_CATALOG,\n" +
 | 
				
			||||||
 | 
					                "       EVENT_OBJECT_SCHEMA,\n" +
 | 
				
			||||||
 | 
					                "       EVENT_OBJECT_TABLE,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_ORDER,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_CONDITION,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_STATEMENT,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_ORIENTATION,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_TIMING,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_REFERENCE_OLD_TABLE,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_REFERENCE_NEW_TABLE,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_REFERENCE_OLD_ROW,\n" +
 | 
				
			||||||
 | 
					                "       ACTION_REFERENCE_NEW_ROW,\n" +
 | 
				
			||||||
 | 
					                "       CREATED,\n" +
 | 
				
			||||||
 | 
					                "       SQL_MODE,\n" +
 | 
				
			||||||
 | 
					                "       DEFINER\n " +
 | 
				
			||||||
 | 
					                "FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA = ? AND EVENT_OBJECT_TABLE = ?";
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            PreparedStatement preparedStatement = configuration.getConnection()
 | 
				
			||||||
 | 
					                    .prepareStatement(sql);
 | 
				
			||||||
 | 
					            preparedStatement.setObject(1, configuration.getDatabaseName());
 | 
				
			||||||
 | 
					            preparedStatement.setObject(2, tableName);
 | 
				
			||||||
 | 
					            ResultSet results = preparedStatement.executeQuery();
 | 
				
			||||||
 | 
					            List<TriggerDoc> triggers = new ArrayList<>();
 | 
				
			||||||
 | 
					            while (results.next()) {
 | 
				
			||||||
 | 
					                String name = results.getString("TRIGGER_NAME");
 | 
				
			||||||
 | 
					                String statement = results.getString("ACTION_STATEMENT");
 | 
				
			||||||
 | 
					                String timing = results.getString("ACTION_TIMING");
 | 
				
			||||||
 | 
					                String manipulation = results.getString("EVENT_MANIPULATION");
 | 
				
			||||||
 | 
					                String created = results.getString("CREATED");
 | 
				
			||||||
 | 
					                TriggerDoc doc = TriggerDoc.builder()
 | 
				
			||||||
 | 
					                        .name(name)
 | 
				
			||||||
 | 
					                        .manipulation(manipulation)
 | 
				
			||||||
 | 
					                        .timing(timing)
 | 
				
			||||||
 | 
					                        .statement(statement)
 | 
				
			||||||
 | 
					                        .createAt(created)
 | 
				
			||||||
 | 
					                        .build();
 | 
				
			||||||
 | 
					                triggers.add(doc);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return triggers;
 | 
				
			||||||
 | 
					        } catch (SQLException e) {
 | 
				
			||||||
 | 
					            log.warn("create trigger doc failed", e);
 | 
				
			||||||
 | 
					            return Collections.emptyList();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -13,11 +13,15 @@ public class TriggerDoc {
 | 
				
			|||||||
    private String name;
 | 
					    private String name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * example 1: BEFORE UPDATE
 | 
					     * example: BEFORE, AFTER
 | 
				
			||||||
     * example 2: AFTER INSERT
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private String timing;
 | 
					    private String timing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * example: INSERT, UPDATE
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String manipulation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String statement;
 | 
					    private String statement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String createAt;
 | 
					    private String createAt;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package com.databasir.core.doc.render;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.databasir.core.doc.model.ColumnDoc;
 | 
					import com.databasir.core.doc.model.ColumnDoc;
 | 
				
			||||||
import com.databasir.core.doc.model.IndexDoc;
 | 
					import com.databasir.core.doc.model.IndexDoc;
 | 
				
			||||||
 | 
					import com.databasir.core.doc.model.TriggerDoc;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.LinkedHashMap;
 | 
					import java.util.LinkedHashMap;
 | 
				
			||||||
@@ -16,12 +17,14 @@ public class RenderConfiguration {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private Boolean renderIndexes = true;
 | 
					    private Boolean renderIndexes = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Boolean renderTriggers = false;
 | 
					    private Boolean renderTriggers = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private LinkedHashMap<String, Function<ColumnDoc, String>> columnTitleAndValueMapping = columnTitleAndValueMapping();
 | 
					    private LinkedHashMap<String, Function<ColumnDoc, String>> columnTitleAndValueMapping = columnTitleAndValueMapping();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private LinkedHashMap<String, Function<IndexDoc, String>> indexTitleAndValueMapping = indexTitleAndValueMapping();
 | 
					    private LinkedHashMap<String, Function<IndexDoc, String>> indexTitleAndValueMapping = indexTitleAndValueMapping();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private LinkedHashMap<String, Function<TriggerDoc, String>> triggerTitleAndValueMapping = triggerTitleAndValueMapping();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected LinkedHashMap<String, Function<ColumnDoc, String>> columnTitleAndValueMapping() {
 | 
					    protected LinkedHashMap<String, Function<ColumnDoc, String>> columnTitleAndValueMapping() {
 | 
				
			||||||
        LinkedHashMap<String, Function<ColumnDoc, String>> mapping = new LinkedHashMap<>();
 | 
					        LinkedHashMap<String, Function<ColumnDoc, String>> mapping = new LinkedHashMap<>();
 | 
				
			||||||
        mapping.put("Name", ColumnDoc::getName);
 | 
					        mapping.put("Name", ColumnDoc::getName);
 | 
				
			||||||
@@ -59,4 +62,14 @@ public class RenderConfiguration {
 | 
				
			|||||||
        mapping.put("Columns", index -> String.join(", ", index.getColumnNames()));
 | 
					        mapping.put("Columns", index -> String.join(", ", index.getColumnNames()));
 | 
				
			||||||
        return mapping;
 | 
					        return mapping;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected LinkedHashMap<String, Function<TriggerDoc, String>> triggerTitleAndValueMapping() {
 | 
				
			||||||
 | 
					        LinkedHashMap<String, Function<TriggerDoc, String>> mapping = new LinkedHashMap<>();
 | 
				
			||||||
 | 
					        mapping.put("Name", TriggerDoc::getName);
 | 
				
			||||||
 | 
					        mapping.put("Timing", trigger -> trigger.getTiming() + " " + trigger.getManipulation());
 | 
				
			||||||
 | 
					        mapping.put("Statement", trigger -> trigger.getStatement().replace("\n", " ")
 | 
				
			||||||
 | 
					                .replace("\r", " "));
 | 
				
			||||||
 | 
					        mapping.put("Create At", TriggerDoc::getCreateAt);
 | 
				
			||||||
 | 
					        return mapping;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,9 @@ public class MarkdownRender implements Render {
 | 
				
			|||||||
                if (config.getRenderIndexes()) {
 | 
					                if (config.getRenderIndexes()) {
 | 
				
			||||||
                    buildIndexes(contentBuilder, table);
 | 
					                    buildIndexes(contentBuilder, table);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                if (config.getRenderTriggers()) {
 | 
				
			||||||
 | 
					                    buildTriggers(contentBuilder, table);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        outputStream.write(contentBuilder.build().getBytes(StandardCharsets.UTF_8));
 | 
					        outputStream.write(contentBuilder.build().getBytes(StandardCharsets.UTF_8));
 | 
				
			||||||
@@ -79,6 +82,22 @@ public class MarkdownRender implements Render {
 | 
				
			|||||||
        contentBuilder.table(indexTitles(), allIndexRows);
 | 
					        contentBuilder.table(indexTitles(), allIndexRows);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void buildTriggers(MarkdownBuilder contentBuilder, TableDoc table) {
 | 
				
			||||||
 | 
					        if (table.getTriggers() == null || table.getTriggers().isEmpty()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        contentBuilder.unorderedList(Collections.singletonList("triggers"));
 | 
				
			||||||
 | 
					        List<List<String>> allRows = table.getTriggers().stream()
 | 
				
			||||||
 | 
					                .map(trigger -> config.getTriggerTitleAndValueMapping()
 | 
				
			||||||
 | 
					                        .values()
 | 
				
			||||||
 | 
					                        .stream()
 | 
				
			||||||
 | 
					                        .map(mapping -> mapping.apply(trigger))
 | 
				
			||||||
 | 
					                        .collect(Collectors.toList()))
 | 
				
			||||||
 | 
					                .collect(Collectors.toList());
 | 
				
			||||||
 | 
					        contentBuilder.table(triggerTitles(), allRows);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private List<String> tableTitles() {
 | 
					    private List<String> tableTitles() {
 | 
				
			||||||
        return new ArrayList<>(config.getColumnTitleAndValueMapping().keySet());
 | 
					        return new ArrayList<>(config.getColumnTitleAndValueMapping().keySet());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -86,4 +105,8 @@ public class MarkdownRender implements Render {
 | 
				
			|||||||
    private List<String> indexTitles() {
 | 
					    private List<String> indexTitles() {
 | 
				
			||||||
        return new ArrayList<>(config.getIndexTitleAndValueMapping().keySet());
 | 
					        return new ArrayList<>(config.getIndexTitleAndValueMapping().keySet());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private List<String> triggerTitles() {
 | 
				
			||||||
 | 
					        return new ArrayList<>(config.getTriggerTitleAndValueMapping().keySet());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import com.databasir.core.doc.factory.DatabaseDocConfiguration;
 | 
					import com.databasir.core.doc.factory.DatabaseDocConfiguration;
 | 
				
			||||||
 | 
					import com.databasir.core.doc.factory.extension.mysql.MysqlTableTriggerDocFactory;
 | 
				
			||||||
import com.databasir.core.doc.factory.jdbc.JdbcDatabaseDocFactory;
 | 
					import com.databasir.core.doc.factory.jdbc.JdbcDatabaseDocFactory;
 | 
				
			||||||
import com.databasir.core.doc.model.DatabaseDoc;
 | 
					import com.databasir.core.doc.model.DatabaseDoc;
 | 
				
			||||||
import com.databasir.core.doc.render.Render;
 | 
					import com.databasir.core.doc.render.Render;
 | 
				
			||||||
@@ -26,12 +27,15 @@ public class App {
 | 
				
			|||||||
        var config = DatabaseDocConfiguration.builder()
 | 
					        var config = DatabaseDocConfiguration.builder()
 | 
				
			||||||
                .databaseName("patient")
 | 
					                .databaseName("patient")
 | 
				
			||||||
                .connection(connection)
 | 
					                .connection(connection)
 | 
				
			||||||
 | 
					                .tableTriggerDocFactory(new MysqlTableTriggerDocFactory())
 | 
				
			||||||
                .build();
 | 
					                .build();
 | 
				
			||||||
        DatabaseDoc doc = JdbcDatabaseDocFactory.of().create(config).orElseThrow();
 | 
					        DatabaseDoc doc = JdbcDatabaseDocFactory.of().create(config).orElseThrow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // render as markdown
 | 
					        // render as markdown
 | 
				
			||||||
        try (FileOutputStream out = new FileOutputStream("doc.md")) {
 | 
					        try (FileOutputStream out = new FileOutputStream("doc.md")) {
 | 
				
			||||||
            Render.markdownRender(new RenderConfiguration()).rendering(doc, out);
 | 
					            RenderConfiguration renderConfig = new RenderConfiguration();
 | 
				
			||||||
 | 
					            renderConfig.setRenderTriggers(true);
 | 
				
			||||||
 | 
					            Render.markdownRender(renderConfig).rendering(doc, out);
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            throw new IllegalStateException(e);
 | 
					            throw new IllegalStateException(e);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user