diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/ExamMysqlKeyword.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/ExamMysqlKeyword.java new file mode 100644 index 00000000..b814dbf9 --- /dev/null +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/ExamMysqlKeyword.java @@ -0,0 +1,35 @@ +package pc.exam.pp.module.exam.dal.dataobject; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@TableName(value = "exam_mysql_keyword", autoResultMap = true) +@Data +@Accessors(chain = true) +@NoArgsConstructor +@AllArgsConstructor +public class ExamMysqlKeyword { + + /** + * 主键id + */ + @TableId(type = IdType.INPUT) + private String keywordId; + /** + * 答案id + */ + private String answerId; + /** + * 关键字 + */ + private String keyword; + /** + * 权值 + */ + private String scoreRate; +} diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/question/ExamMysqlKeywordMapper.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/question/ExamMysqlKeywordMapper.java new file mode 100644 index 00000000..57855fb6 --- /dev/null +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/question/ExamMysqlKeywordMapper.java @@ -0,0 +1,14 @@ +package pc.exam.pp.module.exam.dal.mysql.question; + +import org.apache.ibatis.annotations.Mapper; +import pc.exam.pp.module.exam.dal.dataobject.ExamMysqlKeyword; + +import java.util.List; + +@Mapper +public interface ExamMysqlKeywordMapper { + + List selectListByAnswerId(String answerId); + + String selectByAnswerIds(List answerIdList); +} diff --git a/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/exam/ExamMysqlKeywordMapper.xml b/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/exam/ExamMysqlKeywordMapper.xml new file mode 100644 index 00000000..a9d398ae --- /dev/null +++ b/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/exam/ExamMysqlKeywordMapper.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + select keyword_id, answer_id, keyword, score_rate from exam_mysql_keyword + + + + + + + + + \ No newline at end of file diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/service/mysql/IMysqlServerice.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/service/mysql/IMysqlServerice.java index 3a6554a2..ff032a39 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/service/mysql/IMysqlServerice.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/service/mysql/IMysqlServerice.java @@ -4,13 +4,14 @@ package pc.exam.pp.module.judgement.controller.service.mysql; import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion; import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer; +import java.io.File; import java.io.IOException; import java.sql.SQLException; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public interface IMysqlServerice { - double Judgement(double sorce, ExamQuestion examQuestion) throws IOException, SQLException; + double Judgement(double sorce, File file, ExamQuestion examQuestion) throws IOException, SQLException; diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/service/mysql/MysqlServericeImpl.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/service/mysql/MysqlServericeImpl.java index 895b2196..99c713cd 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/service/mysql/MysqlServericeImpl.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/service/mysql/MysqlServericeImpl.java @@ -1,9 +1,15 @@ package pc.exam.pp.module.judgement.controller.service.mysql; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import pc.exam.pp.module.exam.dal.dataobject.ExamMysqlKeyword; import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion; import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer; import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionKeyword; +import pc.exam.pp.module.exam.dal.mysql.question.ExamMysqlKeywordMapper; +import pc.exam.pp.module.exam.dal.mysql.question.ExamQuestionAnswerMapper; +import pc.exam.pp.module.exam.dal.mysql.question.ExamQuestionMapper; import pc.exam.pp.module.judgement.controller.utils.Mysql.MySQLExporterUtil; import pc.exam.pp.module.judgement.controller.utils.Mysql.SQLComparatorUtil; import pc.exam.pp.module.judgement.controller.utils.Mysql.SqlFileProcessor; @@ -13,7 +19,9 @@ import pc.exam.pp.module.judgement.utils.EndStuMonitorUtils; import java.awt.*; import java.io.*; import java.nio.charset.StandardCharsets; +import java.nio.file.DirectoryStream; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.sql.*; import java.util.*; @@ -24,28 +32,58 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import static pc.exam.pp.module.judgement.controller.utils.Mysql.SQLComparatorUtil.areUpdateStatementsEqual; + @Service public class MysqlServericeImpl implements IMysqlServerice { - static List backupFiles; static String databaseName; - static String answerLogPath = "answerLogMysql.txt"; // 文件路径 + static String databaseNameStu; + static String answerLogPath; // 文件路径 + + @Resource + private ExamMysqlKeywordMapper examMysqlKeywordMapper; + @Resource + private ExamQuestionAnswerMapper examQuestionAnswerMapper; + @Override - public double Judgement(double score, ExamQuestion examQuestion) throws IOException, SQLException { + public double Judgement(double score,File filepath, ExamQuestion examQuestion) throws IOException, SQLException { + List examQuestionAnswers = examQuestionAnswerMapper.selectExamQuestionAnswerByQuId(examQuestion.getQuId()); + String totalKeyScore ="0"; + if (examQuestionAnswers!=null&&examQuestionAnswers.size()>0){ + List answerIdList = examQuestionAnswers.stream() + .map(ExamQuestionAnswer::getAnswerId) // 提取每个对象的 answerId + .collect(Collectors.toList()); + //得到总计得分点 + totalKeyScore=examMysqlKeywordMapper.selectByAnswerIds(answerIdList); - AtomicInteger totalScoreAnswer= new AtomicInteger(); - backupFiles = new ArrayList<>(); // 用于存储生成的备份文件路径 - //todo - //根据考生考试的试卷id,来获取答案文件路径、 原始 数据库SQL 文件路径 + } + answerLogPath = filepath.getParent() + File.separator + "log.txt"; + + AtomicInteger total = new AtomicInteger(); // 文件路径 - String filePath = "C:\\Users\\20373\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\结果素材\\结果素材\\Teacher\\answer.txt"; // 答案文件路径 - String answerPath = "C:\\Users\\20373\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\考试素材\\考试素材\\Student\\db\\db_escape.myd"; // 原始 SQL 文件路径 +// String file = "D:\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\结果素材\\结果素材\\Teacher"; + String file = new File(filepath, "结果").getAbsolutePath(); +// String filePath = "D:\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\结果素材\\结果素材\\Teacher\\answer.txt"; // 答案文件路径 + String filePath = new File(file, "answer.txt").getAbsolutePath(); // 结果/answer.txt + +// String answerPath = "D:\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\结果素材\\结果素材\\Teacher\\db\\db_escape.myd"; // 原始 SQL 文件路径 + String answerPath = new File(new File(file, "db"), "db_escape.myd").getAbsolutePath(); + + +// String fileStu = "D:\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\考试素材\\考试素材\\Student"; + String fileStu = new File(filepath, "素材").getAbsolutePath(); + +// String stuAnswerPath = "D:\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\考试素材\\考试素材\\Student\\db\\db_escape.myd"; + String stuAnswerPath = new File(new File(fileStu, "db"), "db_escape.myd").getAbsolutePath(); // 生成随机数据库名,临时使用 - databaseName = "db_" + UUID.randomUUID().toString().replace("-", "").substring(0, 6); - + databaseName = "db_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8); + databaseNameStu = "db_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8); +// databaseName = "db_6f80867f"; +// databaseNameStu= "db_6f80867e"; // 连接到 MySQL 默认数据库 String url = "jdbc:mysql://localhost:3306/mysql?useSSL=false&serverTimezone=Asia/Shanghai"; String user = "root"; @@ -57,6 +95,11 @@ public class MysqlServericeImpl implements IMysqlServerice { String createDbSql = "CREATE DATABASE " + databaseName; stmt.executeUpdate(createDbSql); System.out.println("已创建数据库:" + databaseName); + String createDbSql2 = "CREATE DATABASE " + databaseNameStu; + stmt.executeUpdate(createDbSql2); + System.out.println("已创建数据库:" + databaseNameStu); + + } @@ -64,767 +107,626 @@ public class MysqlServericeImpl implements IMysqlServerice { e.printStackTrace(); } - // **建立连接到新创建的数据库** +// // **建立连接到新创建的数据库** String newDbUrl = "jdbc:mysql://localhost:3306/" + databaseName + "?useSSL=false&serverTimezone=Asia/Shanghai"; - - // 解析 SQL 文件 - Map> sqlMap = SqlFileProcessor.processSqlFile(filePath); - //select语句(文件对比) - List selectStatements = sqlMap.getOrDefault("SELECT", new ArrayList<>()); - //触发器 (文件对比) - List triggerStatements = sqlMap.getOrDefault("TRIGGER", new ArrayList<>()); - //存储过程 (文件对比) - List procedureStatements = sqlMap.getOrDefault("PROCEDURE", new ArrayList<>()); - //视图 - List viewStatements = sqlMap.getOrDefault("VIEW", new ArrayList<>()); - //删除语句 - List delStatements = sqlMap.getOrDefault("DELETE", new ArrayList<>()); - //其他(建表,新增,修改。结果对比) - List otherStatements = sqlMap.getOrDefault("OTHER", new ArrayList<>()); - // **通过命令行执行 SQL 文件** + String stuDbUrl = "jdbc:mysql://localhost:3306/" + databaseNameStu + "?useSSL=false&serverTimezone=Asia/Shanghai"; + // **通过命令行执行 SQL 文件** 建立 完整正确数据库 boolean sqlFileExecuted = executeSqlFileUsingCommandLine(answerPath, databaseName, user, password); + //建立考生答题数据库 + boolean sqlFileExecutedstu = executeSqlFileUsingCommandLine(stuAnswerPath, databaseNameStu, user, password); - // 执行完 SQL 后,进行数据库导出 - MySQLExporterUtil exporter = new MySQLExporterUtil(databaseName, user, password, "0"); - exporter.export(); + if (sqlFileExecuted && sqlFileExecutedstu) { - List sqlExecutionResults = new ArrayList<>(); - // 如果 SQL 文件执行成功,执行其他 SQL 语句 - if (sqlFileExecuted) { - sqlExecutionResults = executeOtherSqlStatements(otherStatements, newDbUrl, user, password); - } + Map result = readFilesAsMap(file); + Map resultStu = readFilesAsMap(fileStu); + try (Connection conn = DriverManager.getConnection(stuDbUrl, user, password); + Statement stmt = conn.createStatement()) { - //执行完所有的sql语句后,把结果数据库导出来 - MySQLExporterUtil exporterDataBase = new MySQLExporterUtil("mys_010_122", user, password, databaseName); - exporterDataBase.export(); - // 导出的结果数据库文件路径 - String exportedDatabaseFilePath = "./"+databaseName+".sql"; - // 计算与第一个文件的比较结果 - List sqlExecutionResults1 = compareBackupFiles(exportedDatabaseFilePath, sqlExecutionResults); -// System.out.println("====================================更新后的"); -// sqlExecutionResults1.forEach(System.out::println); - //找出所有isvalied为false的,获得对象的sqlStatement, - List invalidResults = sqlExecutionResults1.stream() - .filter(result -> !result.isValid()) - .collect(Collectors.toList()); + System.out.println("已连接学生数据库"); + for (Map.Entry entry : resultStu.entrySet()) { - for (SqlExecutionResult invalidResult : invalidResults) { - String sqlStatement = invalidResult.getSqlStatement(); - //更新语句 - if (sqlStatement.trim().toUpperCase().startsWith("UPDATE")) { + if (entry.getValue().trim().toUpperCase().startsWith("CREATE TABLE")) { + // 正则表达式匹配表名 + Pattern pattern = Pattern.compile("CREATE TABLE\\s+`?(\\w+)`?\\s*\\("); + Matcher matcher = pattern.matcher(entry.getValue()); - appendToFile(answerLogPath,"==================更新语句=================="); - // 提取表名 - Pattern pattern = Pattern.compile("(?i)^UPDATE\\s+([`\\w]+)"); - Matcher matcher = pattern.matcher(sqlStatement); + if (matcher.find()) { + String tableName = matcher.group(1).replace("`", ""); // 获取表名 + System.out.println("表名:" + tableName); + // 获取表名和 SQL 语句 + String createTableSql = entry.getValue(); - if (matcher.find()) { - String tableName = matcher.group(1).replace("`", ""); // 获取表名 - // 从两个 SQL 文件中解析该表的数据 - List> baseData = parseInsertStatements("0.sql", tableName); - List> newData = parseInsertStatements(databaseName+".sql", tableName); + // 执行 CREATE TABLE 语句 + stmt.executeUpdate(createTableSql); + // 查询建表语句 + String showCreateTableSql = "SHOW CREATE TABLE " + tableName; + try (ResultSet rs = stmt.executeQuery(showCreateTableSql)) { + if (rs.next()) { + String createTableSqlExport = rs.getString("Create Table"); + // 替换 result 中的值 + entry.setValue(createTableSqlExport); - // 找到主键字段 - String primaryKey = getPrimaryKeyFromSqlFile("0.sql", tableName); - // 遍历新文件中的记录,检查是否有变化 - for (Map newRecord : newData) { - Map oldRecord = null; - - for (Map baseRecord : baseData) { - if (primaryKey != null && baseRecord.get(primaryKey).equals(newRecord.get(primaryKey))) { - oldRecord = baseRecord; - break; + } } } - if (oldRecord != null && !oldRecord.equals(newRecord)) { - // 数据变化,生成 UPDATE 语句 - List updateSqls = generateUpdateSql(oldRecord, newRecord, tableName); + } - List examQuestionKeywords = new ArrayList<>(); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "UPDATE", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "t_mission", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "5", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "set", "1")); - int totalScoreRate = calculateTotalScoreRate(updateSqls, examQuestionKeywords); - appendToFile(answerLogPath,"✅修改语句得分: " + totalScoreRate); - totalScoreAnswer.addAndGet(totalScoreRate); - } + if (entry.getValue().trim().toUpperCase().startsWith("DELETE")) { + String delStatement = entry.getValue(); + stmt.executeUpdate(delStatement); + } } - } - //插入语句 - if (sqlStatement.trim().toUpperCase().startsWith("INSERT")) { - appendToFile(answerLogPath,"==================插入语句=================="); - // 正则表达式匹配表名 - Pattern pattern = Pattern.compile("INSERT INTO\\s+`?(\\w+)`?\\s*\\("); - Matcher matcher = pattern.matcher(sqlStatement); + for (Map.Entry entry : resultStu.entrySet()) { - if (matcher.find()) { - String tableName = matcher.group(1).replace("`", ""); // 获取表名 - appendToFile(answerLogPath,"表名:"+tableName); + if (entry.getValue().trim().toUpperCase().startsWith("INSERT")) { + // 正则表达式匹配表名 + Pattern pattern = Pattern.compile("INSERT INTO\\s+`?(\\w+)`?\\s*(\\(|VALUES)", Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(entry.getValue()); + if (matcher.find()) { + String tableName = matcher.group(1).replace("`", ""); // 获取表名 + // 获取 INSERT INTO 语句的表格数据并生成新的插入语句 - //获取表明后 - // 从两个 SQL 文件中解析该表的数据 - List> baseData = parseInsertStatements("0.sql", tableName); - List> newData = parseInsertStatements(databaseName+".sql", tableName); - // 根据表名,找出关于此表的 insert 差异语句 - List insertDifferences = findInsertDifferences(baseData, newData); - List examQuestionKeywords=new ArrayList<>(); - examQuestionKeywords.add(new ExamQuestionKeyword("","","INSERT","1")); - examQuestionKeywords.add(new ExamQuestionKeyword("","","INTO","1")); - examQuestionKeywords.add(new ExamQuestionKeyword("","","探险队","1")); - examQuestionKeywords.add(new ExamQuestionKeyword("","","穿梭队","1")); - examQuestionKeywords.add(new ExamQuestionKeyword("","","侦探队","1")); - // 计算总的 scoreRate - int totalScoreRate = calculateTotalScoreRate(insertDifferences, examQuestionKeywords); + String sqlBlock = entry.getValue(); + String[] sqlStatements = sqlBlock.split(";"); - appendToFile(answerLogPath,"✅新增语句得分: " + totalScoreRate); - totalScoreAnswer.addAndGet(totalScoreRate); + for (String sql : sqlStatements) { + sql = sql.trim(); + if (!sql.isEmpty()) { + stmt.executeUpdate(sql); + } + } + + generateInsertStatements(tableName, entry, stuDbUrl, user, password); + + } + } } + } catch (SQLException e) { + e.printStackTrace(); } + try (Connection conn = DriverManager.getConnection(newDbUrl, user, password); + Statement stmt = conn.createStatement()) { + for (Map.Entry entry : result.entrySet()) { - //建表 - if (sqlStatement.trim().toUpperCase().startsWith("CREATE TABLE")){ + if (entry.getValue().trim().toUpperCase().startsWith("CREATE TABLE")) { + List examMysqlKeywordList =new ArrayList<>(); + appendToFile(answerLogPath, "==================建表语句=================="); + for (ExamQuestionAnswer examQuestionAnswer : examQuestionAnswers) { + if (normalize(examQuestionAnswer.getContent()).equals(normalize(entry.getValue()))) { + // 匹配成功 + String answerId = examQuestionAnswer.getAnswerId(); + examMysqlKeywordList= examMysqlKeywordMapper.selectListByAnswerId(answerId); - appendToFile(answerLogPath,"==================建表语句=================="); - // 正则表达式匹配表名 - Pattern pattern = Pattern.compile("CREATE TABLE\\s+`?(\\w+)`?\\s*\\("); - Matcher matcher = pattern.matcher(sqlStatement); + } - if (matcher.find()) { - String tableName = matcher.group(1).replace("`", ""); // 获取表名 - appendToFile(answerLogPath,"表名:"+tableName); + } + // 正则表达式匹配表名 + Pattern pattern = Pattern.compile("CREATE TABLE\\s+`?(\\w+)`?\\s*\\("); + Matcher matcher = pattern.matcher(entry.getValue()); - // 模拟解析 SQL 文件 - Map baseData = parseSqlFile("0.sql"); - Map newData = parseSqlFile(databaseName + ".sql"); - - // 查找 CREATE TABLE 语句 - List createStatements = findCreateTableStatements(baseData, newData, tableName); - - List examQuestionKeywords = new ArrayList<>(); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "CREATE TABLE", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "t_team", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "teamId", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "PRIMARY KEY", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "teamName", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "VARCHAR(50)", "1")); - - // 输出结果 - - // 调用方法,计算得分 - int totalScoreRate = calculateTotalScoreRate(createStatements,examQuestionKeywords); - - appendToFile(answerLogPath,"✅建表语句得分: " + totalScoreRate); - totalScoreAnswer.addAndGet(totalScoreRate); - } - } - - } - // 输出匹配比例 -// invalidResults.forEach(System.out::println); - //视图 - if (viewStatements!=null&&viewStatements.size()>0){ -// System.out.println("=========================答案视图语句"); -// System.out.println(viewStatements); - //解析考生的视图 - List viewAnswerStatements =getAnswerView(exportedDatabaseFilePath); -// System.out.println("=========================考生视图语句"); -// System.out.println(viewAnswerStatements); - - //存储 视图语句的正确性 - List trueViewsql=new ArrayList<>(); - List falseViewsql=new ArrayList<>(); - for (String viewAnswerStatement : viewAnswerStatements) { - appendToFile(answerLogPath,"==================视图语句=================="); - String sqlviewStuAnswer = removeComments(viewAnswerStatement); + if (matcher.find()) { + String tableName = matcher.group(1).replace("`", ""); // 获取表名 - boolean matched = false; // 标志是否找到等价的视图 - for (String viewStatement : viewStatements) { - String sqlviewAnswer = removeComments(viewStatement); + // 查询建表语句 + String showCreateTableSql = "SHOW CREATE TABLE " + tableName; - // 比较两个视图的结果 - // 正则表达式,用于匹配 "VIEW" 后面的视图名称 - String regex = "(?<=VIEW\\s)([\\w`_]+)"; + try (ResultSet rs = stmt.executeQuery(showCreateTableSql)) { + if (rs.next()) { + String createTableSql = rs.getString("Create Table"); + // 替换 result 中的值 + entry.setValue(createTableSql); + String sql1 = result.get(entry.getKey()); + String sql2 = resultStu.get(entry.getKey()); + String normalizedSql1 = simplifyCreateTableSql(sql1); - // 从第一个 SQL 语句中提取视图名称 - String viewNam1 = extractViewName(sqlviewAnswer, regex); - // 从第二个 SQL 语句中提取视图名称 - String viewNam2 = extractViewName(sqlviewStuAnswer, regex); - if (viewNam1.equals(viewNam2)){ + String normalizedSql2 = simplifyCreateTableSql(sql2); - // 随机生成视图名称 - String viewName1 = "v_education_" + UUID.randomUUID().toString().replace("-", ""); - String viewName2 = "v_education_2_" + UUID.randomUUID().toString().replace("-", ""); + if (normalizedSql1.equals(normalizedSql2)) { + // + accumulateScoreAndLog(examMysqlKeywordList,total,answerLogPath,sql2); + } else { + int scoreAnswerNotAllTrue =calculateTotalScoreRate(sql2, examMysqlKeywordList); + total.addAndGet(scoreAnswerNotAllTrue); - // 替换 SQL 语句中的视图名称 - String createView1 = sqlviewAnswer.replace(viewNam1, viewName1); - String createView2 = sqlviewStuAnswer.replace(viewNam2, viewName2); + } - try (Connection conn = DriverManager.getConnection(newDbUrl, user, password); - Statement stmt = conn.createStatement()) { + } + } + + + } + + } + + if (entry.getValue().trim().toUpperCase().startsWith("INSERT")) { + appendToFile(answerLogPath, "==================插入语句=================="); + List examMysqlKeywordList =new ArrayList<>(); + // 正则表达式匹配表名 + Pattern pattern = Pattern.compile("INSERT INTO\\s+`?(\\w+)`?\\s*\\("); + Matcher matcher = pattern.matcher(entry.getValue()); + + if (matcher.find()) { + String tableName = matcher.group(1).replace("`", ""); // 获取表名 + for (ExamQuestionAnswer examQuestionAnswer : examQuestionAnswers) { + if (normalize(examQuestionAnswer.getContent()).equals(normalize(entry.getValue()))) { + // 匹配成功 + String answerId = examQuestionAnswer.getAnswerId(); + examMysqlKeywordList= examMysqlKeywordMapper.selectListByAnswerId(answerId); + + } + + } + // 获取 INSERT INTO 语句的表格数据并生成新的插入语句 + + generateInsertStatements(tableName, entry, newDbUrl, user, password); + String sql1 = result.get(entry.getKey()); + String sql2 = resultStu.get(entry.getKey()); + + + boolean equals = sql1.equals(sql2); + if (equals) { + accumulateScoreAndLog(examMysqlKeywordList,total,answerLogPath,sql2); + + } else { + int scoreAnswerNotAllTrue =calculateTotalScoreRate(sql2, examMysqlKeywordList); + total.addAndGet(scoreAnswerNotAllTrue); + + } + + + } + + + } + + if (entry.getValue().trim().toUpperCase().startsWith("DELETE")) { + appendToFile(answerLogPath, "==================删除语句=================="); + List examMysqlKeywordList =new ArrayList<>(); + String delStatement = entry.getValue(); + delStatement = delStatement.trim().replaceAll(";+\\s*$", ""); + + String sql2 = resultStu.get(entry.getKey()); + // 正则提取表名和 WHERE 条件 + Pattern pattern = Pattern.compile("DELETE\\s+FROM\\s+(\\w+)\\s+WHERE\\s+(.+)", Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(delStatement); + for (ExamQuestionAnswer examQuestionAnswer : examQuestionAnswers) { + if (normalize(examQuestionAnswer.getContent()).equals(normalize(entry.getValue()))) { + // 匹配成功 + String answerId = examQuestionAnswer.getAnswerId(); + examMysqlKeywordList= examMysqlKeywordMapper.selectListByAnswerId(answerId); + + } + + } + if (matcher.find()) { + String tableName = matcher.group(1).trim(); + String whereClause = matcher.group(2).trim(); + MysqlServericeImpl.DeleteInfo deleteInfo = new MysqlServericeImpl.DeleteInfo(tableName, whereClause); + appendToFile(answerLogPath, "提取出的表名: " + deleteInfo.tableName); + appendToFile(answerLogPath, "提取出的条件: " + deleteInfo.whereClause); + // 构造验证 SQL + String verifySql = "SELECT COUNT(*) FROM " + deleteInfo.tableName + " WHERE " + deleteInfo.whereClause; + appendToFile(answerLogPath, "验证 SQL: " + verifySql); + //查找正确答案的 +// try (Connection conn = DriverManager.getConnection(newDbUrl, user, password); +// Statement stmt = conn.createStatement()) { + try (ResultSet rs = stmt.executeQuery(verifySql)) { + if (rs.next()) { + int count = rs.getInt(1); + if (count == 0) { + try (Connection connstu = DriverManager.getConnection(stuDbUrl, user, password); + Statement stmtstu = connstu.createStatement()) { + try (ResultSet rsstu = stmtstu.executeQuery(verifySql)) { + if (rsstu.next()) { + int countstu = rs.getInt(1); + if (countstu == 0) { + //累加删除语句的所有权值 examQuestionKeywords累加scorerate + appendToFile(answerLogPath, "验证通过:符合 DELETE 条件的记录已删除。"); + + accumulateScoreAndLog(examMysqlKeywordList,total,answerLogPath,sql2); + + } else { + + int scoreAnswerNotAllTrue =calculateTotalScoreRate(sql2, examMysqlKeywordList); + total.addAndGet(scoreAnswerNotAllTrue); + + } + } + } + } + + + } else { + appendToFile(answerLogPath, "验证失败:还有 " + count + " 条记录符合 DELETE 条件,未被删除。"+"得分:0 ❌"); + } + } + + } catch (SQLException e) { + appendToFile(answerLogPath, "执行验证 SQL 出错!"); + e.printStackTrace(); + } + + } + + } + + if (entry.getValue().trim().toUpperCase().startsWith("UPDATE")) { + appendToFile(answerLogPath, "==================更新语句=================="); + List examMysqlKeywordList =new ArrayList<>(); + String sql1 = entry.getValue(); + for (ExamQuestionAnswer examQuestionAnswer : examQuestionAnswers) { + if (normalize(examQuestionAnswer.getContent()).equals(normalize(entry.getValue()))) { + // 匹配成功 + String answerId = examQuestionAnswer.getAnswerId(); + examMysqlKeywordList= examMysqlKeywordMapper.selectListByAnswerId(answerId); + + } + + } + //根据entry的key 获得resultStu 的value + + // 根据 key 获取另一个文件中的 SQL 语句 + String sql2 = resultStu.get(entry.getKey()); + + + boolean b = areUpdateStatementsEqual(sql1, sql2); + + // + if (b) { + accumulateScoreAndLog(examMysqlKeywordList,total,answerLogPath,sql2); + } else { + int scoreAnswerNotAllTrue =calculateTotalScoreRate(sql2, examMysqlKeywordList); + total.addAndGet(scoreAnswerNotAllTrue); +// appendToFile(answerLogPath,"语句"+sql2+"不正确,关键得分:"+scoreAnswerNotAllTrue+ "❌"); + + } + + + } + if (entry.getValue().trim().toUpperCase().startsWith("SELECT")) { + List examMysqlKeywordList =new ArrayList<>(); + for (ExamQuestionAnswer examQuestionAnswer : examQuestionAnswers) { + if (normalize(examQuestionAnswer.getContent()).equals(normalize(entry.getValue()))) { + // 匹配成功 + String answerId = examQuestionAnswer.getAnswerId(); + examMysqlKeywordList= examMysqlKeywordMapper.selectListByAnswerId(answerId); + + } + + } + String sql1 = entry.getValue(); + + String sql2 = resultStu.get(entry.getKey()); + + + List> answerList; + List> answerListStu = new ArrayList<>(); + try (Connection connanswer = DriverManager.getConnection(newDbUrl, user, password); + Statement stmtan = connanswer.createStatement()) { + try (ResultSet answer = stmtan.executeQuery(sql1)) { + answerList = getAnswerList(answer); + printResult(answerList); + } + } + try (Connection connstu = DriverManager.getConnection(stuDbUrl, user, password); + Statement stmtstu = conn.createStatement()) { + try (ResultSet answer = stmtstu.executeQuery(sql2)) { + answerListStu = getAnswerList(answer); + printResult(answerListStu); + } catch (SQLException e) { + appendToFile(answerLogPath, "执行学生库语句"+sql2+"时发生错误: " + e.getMessage()+"得分:0 ❌"); + } + + + } + + boolean isEquivalent = compareResultsSelect(answerList, answerListStu); + + if (isEquivalent) { + //todo 得分 + accumulateScoreAndLog(examMysqlKeywordList,total,answerLogPath,sql2); + + + } else { + int scoreAnswerNotAllTrue =calculateTotalScoreRate(sql2, examMysqlKeywordList); + total.addAndGet(scoreAnswerNotAllTrue); +// appendToFile(answerLogPath,"语句"+sql2+"不正确,关键得分:"+scoreAnswerNotAllTrue+ "❌"); + + } + + + } + + + if (entry.getValue().trim().replaceAll("\\s+", " ").matches("(?i)^CREATE( OR REPLACE)?( ALGORITHM\\s*=\\s*\\w+)?( DEFINER\\s*=\\s*[`\"'\\w@%\\.]+)?( SQL SECURITY \\w+)? VIEW\\b.*")) { + appendToFile(answerLogPath, "==================视图语句=================="); + List examMysqlKeywordList =new ArrayList<>(); + for (ExamQuestionAnswer examQuestionAnswer : examQuestionAnswers) { + if (normalize(examQuestionAnswer.getContent()).equals(normalize(entry.getValue()))) { + // 匹配成功 + String answerId = examQuestionAnswer.getAnswerId(); + examMysqlKeywordList= examMysqlKeywordMapper.selectListByAnswerId(answerId); + + } + + } + String sql1 = entry.getValue(); + String sql2 = resultStu.get(entry.getKey()); + // 正则表达式,用于匹配 "VIEW" 后面的视图名称 + String regex = "(?<=VIEW\\s)([\\w`_]+)"; + String sqlviewAnswer = removeComments(sql1); + String sqlviewAnswerStu = removeComments(sql2); + + if (StringUtils.isNotBlank(sqlviewAnswerStu)) { + // 从第一个 SQL 语句中提取视图名称 + String viewNam1 = extractViewName(sqlviewAnswer, regex); + // 从第二个 SQL 语句中提取视图名称 + String viewNam2 = extractViewName(sqlviewAnswerStu, regex); + // 随机生成视图名称 + String viewName1 = "v_education_" + UUID.randomUUID().toString().replace("-", ""); + String viewName2 = "v_education_2_" + UUID.randomUUID().toString().replace("-", ""); + + + // 替换 SQL 语句中的视图名称 + String createView1 = sqlviewAnswer.replace(viewNam1, viewName1); + String createView2 = sqlviewAnswerStu.replace(viewNam2, viewName2); + + +// try (Connection conn = DriverManager.getConnection(newDbUrl, user, password); +// Statement stmt = conn.createStatement()) { + // 执行 CREATE VIEW 语句,创建视图 stmt.execute(createView1); - stmt.execute(createView2); + + try { + stmt.execute(createView2); + + } catch (SQLException e) { + appendToFile(answerLogPath, "执行学生库语句"+createView2+"时发生错误: " + e.getMessage()+"得分:0 ❌"); + } // 执行查询,获取视图1的结果 - appendToFile(answerLogPath,"执行视图 " + viewName1 + " 的查询结果:"); - - - String sql1 = "SELECT * FROM " + viewName1; - List> result1 = executeQuery(stmt, sql1); + appendToFile(answerLogPath, "执行正确答案视图语句" + viewName1 + " 的查询结果:"); + String sql3 = "SELECT * FROM " + viewName1; + List> result1 = executeQuery(stmt, sql3); printResult(result1); - // 执行查询,获取视图2的结果 - appendToFile(answerLogPath,"执行视图 " + viewName2 + " 的查询结果:"); - String sql2 = "SELECT * FROM " + viewName2; - List> result2 = executeQuery(stmt, sql2); + appendToFile(answerLogPath, "执行考生视图语句" + viewName2 + " 的查询结果:"); + String sql4 = "SELECT * FROM " + viewName2; + List> result2 = executeQuery(stmt, sql4); printResult(result2); // 比较两个视图的结果 boolean isEquivalent = compareResults(result1, result2); - appendToFile(answerLogPath,"\n是否结果等价: " + isEquivalent); + appendToFile(answerLogPath, "\n是否结果等价: " + isEquivalent); + // 删除视图 System.out.println("\n删除视图 " + viewName1 + " 和 " + viewName2 + "..."); stmt.execute("DROP VIEW IF EXISTS " + viewName1); stmt.execute("DROP VIEW IF EXISTS " + viewName2); if (isEquivalent) { - trueViewsql.add(sqlviewStuAnswer); - matched = true; - break; // 找到等价视图就跳出内层循环 + accumulateScoreAndLog(examMysqlKeywordList,total,answerLogPath,sql2); + + } else { + int scoreAnswerNotAllTrue =calculateTotalScoreRate(sql2, examMysqlKeywordList); + total.addAndGet(scoreAnswerNotAllTrue); + } - } catch (SQLException e) { - e.printStackTrace(); +// } + + } } - } - // 如果没有找到等价视图 - if (!matched) { - falseViewsql.add(sqlviewStuAnswer); - } - } + //存储过程 + if (entry.getValue().trim().toUpperCase().toUpperCase().contains("PROCEDURE")) { + List examMysqlKeywordList =new ArrayList<>(); + for (ExamQuestionAnswer examQuestionAnswer : examQuestionAnswers) { + if (normalize(examQuestionAnswer.getContent()).equals(normalize(entry.getValue()))) { + // 匹配成功 + String answerId = examQuestionAnswer.getAnswerId(); + examMysqlKeywordList= examMysqlKeywordMapper.selectListByAnswerId(answerId); - List examQuestionKeywords = new ArrayList<>(); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "CREATE", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "VIEW", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "v_score", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "`t_room`.`themeName` AS `themeName`", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "`t_mission`.`description` AS `description`", "1")); - examQuestionKeywords.add(new ExamQuestionKeyword("", "", "`t_team`.`teamName` AS `teamName`", "1")); - //拿出正确的语句 - int totalScore = 0; + } - if (trueViewsql!=null&&trueViewsql.size()>0){ - //获得 此答案下的所有考点权值 -// System.out.println(trueViewsql); - - for (ExamQuestionKeyword keyword : examQuestionKeywords) { - String scoreRateStr = keyword.getScoreRate(); // 假设你有 getScorerate() 方法 - if (scoreRateStr != null && !scoreRateStr.isEmpty()) { - try { - totalScore += Integer.parseInt(scoreRateStr); - } catch (NumberFormatException e) { - System.err.println("无效的分数值: " + scoreRateStr); } - } - } - appendToFile(answerLogPath,"✅等价视图语句得分为: " + totalScore); - } - if (falseViewsql != null && !falseViewsql.isEmpty()) { - System.out.println("//判断 关键点权值"); - for (ExamQuestionKeyword keyword : examQuestionKeywords) { - String key = keyword.getKeyword(); - String scoreRateStr = keyword.getScoreRate(); + appendToFile(answerLogPath, "==================储存过程=================="); + String sql1 = entry.getValue(); + + String sql2 = resultStu.get(entry.getKey()); + //提取call语句 + List extractCallStatements = extractCallStatements(sql1); + //标准答案 集合 + List> anwerResults = new ArrayList<>(); + //考生答案 集合 + List> stuResults = new ArrayList<>(); + if (extractCallStatements != null && extractCallStatements.size() > 0) { + for (String extractCallStatement : extractCallStatements) { + appendToFile(answerLogPath, "测试 call 语句:" + extractCallStatement); + - if (key != null && !key.isEmpty()) { - for (String sql : falseViewsql) { - if (sql.contains(key)) { try { - if (scoreRateStr != null && !scoreRateStr.isEmpty()) { - totalScore += Integer.parseInt(scoreRateStr); - } - } catch (NumberFormatException e) { - System.err.println("无效的分数值: " + scoreRateStr); +// try (Connection conn = DriverManager.getConnection(newDbUrl, user, password); +// Statement stmt = conn.createStatement()) { + ResultSet newResult = stmt.executeQuery(extractCallStatement); + anwerResults.addAll(extractResults(newResult)); +// } + } catch (SQLException e) { + appendToFile(answerLogPath, "执行标准库 SQL CALL 语句时发生错误: " + e.getMessage()); } - break; // 找到一次匹配就跳出内层循环,避免重复加分 - } - } - } - } - appendToFile(answerLogPath,"✅不等价视图中匹配到的关键点总得分为: " + totalScore); - totalScoreAnswer.addAndGet(totalScore); - } - } - - try (Connection conn = DriverManager.getConnection(newDbUrl, user, password); - Statement stmt = conn.createStatement()) { + try (Connection connstu = DriverManager.getConnection(stuDbUrl, user, password); + Statement stmtstu = connstu.createStatement()) { + stmtstu.execute(sql2); // 创建存储过程 + try { - List examQuestionKeywords=new ArrayList<>(); - examQuestionKeywords.add(new ExamQuestionKeyword("","","DELETE FROM t_room","1")); - examQuestionKeywords.add(new ExamQuestionKeyword("","","WHERE","1")); - examQuestionKeywords.add(new ExamQuestionKeyword("","","roomId =1","1")); - - int scoreRateSum = 0; // 最终得分累计 - - // 在方法中处理 delStatements - if (delStatements != null && delStatements.size() > 0) { - appendToFile(answerLogPath,"==================删除语句=================="); - for (String delStatement : delStatements) { - - - delStatement = delStatement.trim().replaceAll(";+\\s*$", ""); - - // 正则提取表名和 WHERE 条件 - Pattern pattern = Pattern.compile("DELETE\\s+FROM\\s+(\\w+)\\s+WHERE\\s+(.+)", Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(delStatement); - - if (matcher.find()) { - String tableName = matcher.group(1).trim(); - String whereClause = matcher.group(2).trim(); - DeleteInfo deleteInfo = new DeleteInfo(tableName, whereClause); - appendToFile(answerLogPath,"提取出的表名: " + deleteInfo.tableName); - appendToFile(answerLogPath,"提取出的条件: " + deleteInfo.whereClause); - // 构造验证 SQL - String verifySql = "SELECT COUNT(*) FROM " + deleteInfo.tableName + " WHERE " + deleteInfo.whereClause; - appendToFile(answerLogPath,"验证 SQL: " + verifySql); - try (ResultSet rs = stmt.executeQuery(verifySql)) { - if (rs.next()) { - int count = rs.getInt(1); - if (count == 0) { - //累加删除语句的所有权值 examQuestionKeywords累加scorerate - appendToFile(answerLogPath,"验证通过:符合 DELETE 条件的记录已删除。"); - for (ExamQuestionKeyword keyword : examQuestionKeywords) { - scoreRateSum += Integer.parseInt(keyword.getScoreRate()); + ResultSet oldResult = stmtstu.executeQuery(extractCallStatement); + stuResults.addAll(extractResults(oldResult)); + } catch (SQLException e) { + appendToFile(answerLogPath, "执行学生库 SQL CALL 语句时发生错误: " + e.getMessage()); } - } else { - appendToFile(answerLogPath,"验证失败:还有 " + count + " 条记录符合 DELETE 条件,未被删除。"); + // 比较结果 + boolean flag = compareExtractResults(anwerResults, stuResults); + + if (flag) { + //todo 得分 + accumulateScoreAndLog(examMysqlKeywordList,total,answerLogPath,sql2); + + } else { + //得分 + int scoreAnswerNotAllTrue =calculateTotalScoreRate(sql2, examMysqlKeywordList); + total.addAndGet(scoreAnswerNotAllTrue); + + + } + + + } catch (SQLException e) { + appendToFile(answerLogPath, "执行学生库语句"+sql2+"时发生错误: " + e.getMessage()+"得分:0 ❌"); } } - } catch (SQLException e) { - appendToFile(answerLogPath,"执行验证 SQL 出错!"); - e.printStackTrace(); - } - } else { - appendToFile(answerLogPath,"未能从 SQL 中提取 DELETE 信息!"); - } - } - } - totalScoreAnswer.addAndGet(scoreRateSum); - - appendToFile(answerLogPath,"✅删除正确最终得分: " + scoreRateSum); - String directoryPath = "C:\\Users\\20373\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\结果素材\\结果素材\\Teacher"; - - - //select语句 - if (selectStatements != null && selectStatements.size() > 0) { - appendToFile(answerLogPath,"==================查找语句=================="); -// selectStatements.forEach(System.out::println); - - for (String selectStatement : selectStatements) { - String normalizedSelect = selectStatement.trim().replaceAll("\\s+", "").toLowerCase(); - AtomicBoolean foundMatch = new AtomicBoolean(false); // 添加标记变量 - try { - Files.walk(Paths.get(directoryPath)) - .filter(Files::isRegularFile) - .forEach(filePaths -> { - try { - String fileContent = Files.readString(filePaths, StandardCharsets.UTF_8); - String normalizedFileContent = fileContent.trim().replaceAll("\\s+", "").toLowerCase(); - - if (normalizedSelect.equals(normalizedFileContent)) { - - String stuPath="C:\\Users\\20373\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\考试素材\\考试素材\\Student\\"+filePaths.getFileName(); -// System.out.println("结果语句:"+selectStatement); - - - String stuAnswer = readSQLFromFile(stuPath); -// System.out.println("考生语句"+stuAnswer); - List> answerList; - try (ResultSet answer = stmt.executeQuery(selectStatement) ) { - answerList = getAnswerList(answer); - } - List> stuanswerList ; - try (ResultSet stuanswer = stmt.executeQuery(stuAnswer) ) { - stuanswerList = getAnswerList(stuanswer); - } - appendToFile(answerLogPath,"执行考生答案的查询结果:"); - printResult(answerList); - appendToFile(answerLogPath,"执行正确答案的查询结果:"); - printResult(stuanswerList); - - - boolean isEquivalent = compareResultsSelect(answerList, stuanswerList); - appendToFile(answerLogPath,"\n是否结果等价: " + isEquivalent); - if (isEquivalent){ - foundMatch.set(true); // 设为 true,表示找到了匹配 - } - - } - } catch (Exception e) { - appendToFile(answerLogPath,"读取文件失败:" + filePaths); - e.printStackTrace(); - } - } - - - ); - int totalScore = 0; - //判断标记是否为true - if (foundMatch.get()) { - //todo 根据试题答案id去找 答案下的关键字 - List examQuestionKeywordsql=new ArrayList<>(); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","description AS 超时任务描述","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","earnedScore AS 实际得分","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","baseScore AS 基础分","1")); - - for (ExamQuestionKeyword keywordObj : examQuestionKeywordsql) { - totalScore += Integer.parseInt(keywordObj.getScoreRate()); - } } else { - System.out.println("该 SQL 在任何文件中都未找到匹配或结果不等价:\n" + selectStatement); - List examQuestionKeywordsql=new ArrayList<>(); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","description AS 任务描述","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","teamName AS 队伍名称","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","isCompleted = 0","1")); - - for (ExamQuestionKeyword keywordObj : examQuestionKeywordsql) { - if (selectStatement.contains(keywordObj.getKeyword())) { - totalScore += Integer.parseInt(keywordObj.getScoreRate()); - } - } + appendToFile(answerLogPath, "此存储过程无 CALL 语句"); } - totalScoreAnswer.addAndGet(totalScore); - appendToFile(answerLogPath,"✅当前查询SQL得分为:" + totalScore); - } catch (IOException e) { - appendToFile(answerLogPath,"遍历目录出错!"); - e.printStackTrace(); + } + if (entry.getValue().trim().toUpperCase().toUpperCase().contains("TRIGGER")) { + appendToFile(answerLogPath, "==================触发器=================="); + List examMysqlKeywordList =new ArrayList<>(); + for (ExamQuestionAnswer examQuestionAnswer : examQuestionAnswers) { + if (normalize(examQuestionAnswer.getContent()).equals(normalize(entry.getValue()))) { + // 匹配成功 + String answerId = examQuestionAnswer.getAnswerId(); + examMysqlKeywordList= examMysqlKeywordMapper.selectListByAnswerId(answerId); + + } + + } + String sql1 = entry.getValue(); + + String sql2 = resultStu.get(entry.getKey()); + + // 清洗触发器语句(去除注释等) + String triggerStatementCleanSql1 = cleanProcedureSQL(sql1); + + // 标准化触发器内容(去空格、换行、小写) + String normalizedTriggerSql1 = triggerStatementCleanSql1.trim().replaceAll("\\s+", "").toLowerCase(); + + + // 清洗触发器语句(去除注释等) + String triggerStatementCleanSql2 = cleanProcedureSQL(sql2); + + // 标准化触发器内容(去空格、换行、小写) + String normalizedTriggerSql2 = triggerStatementCleanSql2.trim().replaceAll("\\s+", "").toLowerCase(); + + boolean equals = normalizedTriggerSql1.equals(normalizedTriggerSql2); + if (equals) { + //todo 得分 + accumulateScoreAndLog(examMysqlKeywordList,total,answerLogPath,sql2); + } else { + int scoreAnswerNotAllTrue =calculateTotalScoreRate(sql2, examMysqlKeywordList); + total.addAndGet(scoreAnswerNotAllTrue); + + } + + } } - } - - - - - - } catch (SQLException e) { - throw new RuntimeException(e); - } - - - //触发器 - - // 触发器处理 - if (triggerStatements != null && triggerStatements.size() > 0) { - appendToFile(answerLogPath,"==================触发器语句=================="); - for (String triggerStatement : triggerStatements) { - String directoryPath = "C:\\Users\\20373\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\结果素材\\结果素材\\Teacher"; - - - - // 清洗触发器语句(去除注释等) - String triggerStatementClean = cleanProcedureSQL(triggerStatement); - - // 标准化触发器内容(去空格、换行、小写) - String normalizedTrigger = triggerStatementClean.trim().replaceAll("\\s+", "").toLowerCase(); - - AtomicBoolean foundMatch = new AtomicBoolean(false); - - try { - Files.walk(Paths.get(directoryPath)) - .filter(Files::isRegularFile) - .forEach(filePathtir -> { - try { - String fileContent = Files.readString(filePathtir, StandardCharsets.UTF_8); - String normalizedFileContent = fileContent.trim().replaceAll("\\s+", "").toLowerCase(); - - if (normalizedTrigger.equals(normalizedFileContent)) { - - foundMatch.set(true); - // 学生答题路径 - String stuPath="C:\\Users\\20373\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\考试素材\\考试素材\\Student\\"+filePathtir.getFileName(); - //考试素材 - String examPath=directoryPath+"\\"+filePathtir.getFileName(); - - - String stuAnswer = readSQLFromFile(stuPath); - - String examAnswer =readSQLFromFile(examPath); - - // 预处理两个字符串:去除所有空白符(空格、制表符、换行) - String processedTrigger = examAnswer.replaceAll("\\s+", "").toLowerCase(); - String processedAnswer = stuAnswer.replaceAll("\\s+", "").toLowerCase(); - - // 比较是否完全相等 - int totalScore=0; - List examQuestionKeywordsql=new ArrayList<>(); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","CREATE TRIGGER tri_calculate_score","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","BEFORE INSERT ON t_mission_completion","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","WHERE missionId = NEW.missionId","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","IF NEW.isCompleted = 1 THEN","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","IF NEW.completionTime <= v_base_time THEN","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","ELSE","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","END IF","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","ELSE SET NEW.earnedScore = 0; END IF","1")); - if (processedTrigger.equals(processedAnswer)) { - appendToFile(answerLogPath,"考生答案与标准答案语句内容一致(忽略格式)"); - - for (ExamQuestionKeyword keywordObj : examQuestionKeywordsql) { - totalScore += Integer.parseInt(keywordObj.getScoreRate()); - } - }else { - for (ExamQuestionKeyword examQuestionKeyword : examQuestionKeywordsql) { - String keyword = Pattern.quote(examQuestionKeyword.getKeyword()); - Pattern pattern = Pattern.compile("\\b" + keyword + "\\b", Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(stuAnswer); - - if (matcher.find()) { - totalScore += Integer.parseInt(examQuestionKeyword.getScoreRate()); - } - - } - } - totalScoreAnswer.addAndGet(totalScore); - appendToFile(answerLogPath,"✅触发器得分点"+totalScore); - } - } catch (IOException e) { - appendToFile(answerLogPath,"读取文件失败: " + filePath + ",错误: " + e.getMessage()); - } - }); - - if (!foundMatch.get()) { - appendToFile(answerLogPath,"未找到匹配触发器:" + triggerStatement.substring(0, Math.min(triggerStatement.length(), 100)) + "..."); - } - - } catch (IOException e) { - appendToFile(answerLogPath,"遍历学生目录出错: " + e.getMessage()); - - } + // try (Connection conn = DriverManager.getConnection(newDbUrl, user, password); +// Statement stmt = conn.createStatement()) { + //删除临时创建的数据库databaseName + String dropDbSql = "DROP DATABASE " + databaseName; + stmt.executeUpdate(dropDbSql); + String dropDbSql2 = "DROP DATABASE " + databaseNameStu; + stmt.executeUpdate(dropDbSql2); +// } } } + double roundedResult =0.0; + try { + int totalKeyScoreInt = Integer.parseInt(totalKeyScore.trim()); + if (totalKeyScoreInt != 0) { + double result = (total.get() * 1.0 / totalKeyScoreInt) * score; - - - //储存过程 - if (procedureStatements!=null&&procedureStatements.size()>0){ - appendToFile(answerLogPath,"==================储存过程=================="); - for (String procedureStatement : procedureStatements) { - //根据 存储过程语句 查找 文件名 - String directoryPath = "C:\\Users\\20373\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\结果素材\\结果素材\\Teacher"; - - String procedureStatementClean = cleanProcedureSQL(procedureStatement); - String normalizedProcedure = procedureStatementClean.trim().replaceAll("\\s+", "").toLowerCase(); - AtomicBoolean foundMatch = new AtomicBoolean(false); - - try { - Files.walk(Paths.get(directoryPath)) - .filter(Files::isRegularFile) - .forEach(filePathpro -> { - try { - String fileContent = Files.readString(filePathpro, StandardCharsets.UTF_8); - String normalizedFileContent = fileContent.trim().replaceAll("\\s+", "").toLowerCase(); - - if (normalizedProcedure.equals(normalizedFileContent)) { -// System.out.println("匹配成功!存储过程在文件中找到: " + filePathpro.getFileName()); - foundMatch.set(true); - - - List extractCallStatements = extractCallStatements(procedureStatement); -// String callStatement = extractCallStatements(procedureStatement); - // 输出提取的 CALL 语句 - if (extractCallStatements != null&&extractCallStatements.size()>0) { - for (String extractCallStatement : extractCallStatements) { - appendToFile(answerLogPath,"测试语句:"+extractCallStatement); - } - - } else { - appendToFile(answerLogPath,"未找到 CALL 语句"); - } - //todo 学生数据库 - String userDb="mys_010_122"; - String stuDbUrl = "jdbc:mysql://localhost:3306/" + userDb + "?useSSL=false&serverTimezone=Asia/Shanghai"; - try (Connection newConn = DriverManager.getConnection(newDbUrl, user, password); - Statement newStmt = newConn.createStatement()) { - //这里先执行 procedureStatement 语句 - - // 第一个数据库:创建存储过程 - newStmt.execute(procedureStatementClean); // 创建存储过程 - - // 执行第一个数据库的 CALL 语句并获取结果 - - List> newResults = new ArrayList<>(); - if (extractCallStatements != null && !extractCallStatements.isEmpty()) { - for (String extractCallStatement : extractCallStatements) { - try { - ResultSet newResult = newStmt.executeQuery(extractCallStatement); - newResults.addAll(extractResults(newResult)); - } catch (SQLException e) { - appendToFile(answerLogPath, "执行标准库 SQL CALL 语句时发生错误: " + e.getMessage()); - } - } - } - - - - try (Connection oldConn = DriverManager.getConnection(stuDbUrl, user, password); - Statement oldStmt = oldConn.createStatement()) { - String stuPath="C:\\Users\\20373\\Desktop\\202504211120_mysql\\71\\MYS_010_122\\考试素材\\考试素材\\Student\\"+filePathpro.getFileName(); - - String stuAnswer = readSQLFromFile(stuPath); - - try { - //把学生答题路径下的文件sql拿出,创建存储过程 - oldStmt.execute(stuAnswer); - - } catch (SQLException e) { - appendToFile(answerLogPath,"执行 SQL 语句时发生错误: " + e.getMessage()); - - } - - List> oldResults = new ArrayList<>(); - if (extractCallStatements != null && !extractCallStatements.isEmpty()) { - for (String extractCallStatement : extractCallStatements) { - try { - ResultSet oldResult = oldStmt.executeQuery(extractCallStatement); - oldResults.addAll(extractResults(oldResult)); - } catch (SQLException e) { - appendToFile(answerLogPath, "执行学生库 SQL CALL 语句时发生错误: " + e.getMessage()); - } - } - } - - - - // 比较结果 - boolean b = compareExtractResults(newResults, oldResults); - - appendToFile(answerLogPath,"考生答案与标准答案语句结果为:"+b ); - - - int totalScore=0; - List examQuestionKeywordsql=new ArrayList<>(); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","PROCEDURE","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","pro_getMaxScore","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","in_theme_keyword","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","VARCHAR(50)","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","WHERE","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","LIKE","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","CONCAT","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","DESC","1")); - examQuestionKeywordsql.add(new ExamQuestionKeyword("","","LIMIT","1")); - if (b){ - for (ExamQuestionKeyword keywordObj : examQuestionKeywordsql) { - totalScore += Integer.parseInt(keywordObj.getScoreRate()); - } - }else { - - for (ExamQuestionKeyword keywordObj : examQuestionKeywordsql) { - if (stuAnswer.contains(keywordObj.getKeyword())) { - totalScore += Integer.parseInt(keywordObj.getScoreRate()); - } - } - - } - appendToFile(answerLogPath,"✅存储过程得分"+totalScore); - - totalScoreAnswer.addAndGet(totalScore); - } catch (SQLException e) { - System.out.println("Error connecting to old database: " + e.getMessage()); - } - - //删除临时创建的数据库databaseName - String dropDbSql = "DROP DATABASE " + databaseName; - newStmt.executeUpdate(dropDbSql); - System.out.println("已删除数据库:" + databaseName); - } catch (SQLException e) { - System.out.println("Error connecting to new database: " + e.getMessage()); - } - - - - - - - } - - } catch (IOException e) { - e.printStackTrace(); - } - }); - - if (!foundMatch.get()) { - - System.out.println("❌ 没有找到匹配的存储过程文件: \n" + procedureStatementClean); - } - - } catch (IOException e) { - e.printStackTrace(); - } - } - } - //把生成的文件删掉 - File file = new File(exportedDatabaseFilePath); - if (file.exists()) { - file.delete(); - } else { - System.out.println("文件不存在: " + file); - } - for (String backupFile : backupFiles) { - File fileback = new File(backupFile); - if (fileback.exists()) { - fileback.delete(); + // 保留两位小数 + // 保留两位小数的 double(四舍五入) + roundedResult = Math.round(result * 100.0) / 100.0; + System.out.println("最终结果是:" + roundedResult); } else { - System.out.println("文件不存在: " + fileback); + System.out.println("除数不能为 0"); + } + } catch (NumberFormatException e) { + System.out.println("无效的 totalKeyScore 值:" + totalKeyScore); + } + return roundedResult; + } + public static void accumulateScoreAndLog(List examMysqlKeywordList, AtomicInteger total, String answerLogPath, String sql2) { + AtomicInteger singleTotal = new AtomicInteger(); // 单独累加 scoreRateStr 的总和 + for (ExamMysqlKeyword examMysqlKeyword : examMysqlKeywordList) { + String scoreRateStr = examMysqlKeyword.getScoreRate(); + if (scoreRateStr != null && !scoreRateStr.trim().isEmpty()) { + try { + int scoreAnswerAllTrue = Integer.parseInt(scoreRateStr.trim()); + total.addAndGet(scoreAnswerAllTrue); + + singleTotal.addAndGet(scoreAnswerAllTrue); // 单独累加 + } catch (NumberFormatException e) { + System.err.println("无效的scoreRate值:" + scoreRateStr); + } } } - String totalscore = "44"; - double Score = score * (totalScoreAnswer.get() / Double.parseDouble(totalscore)); - - - return Score; - - - - + appendToFile(answerLogPath, "语句" + sql2 + "正确,关键得分:" + singleTotal+ "✅"); } + public static int calculateTotalScoreRate(String sql, List examQuestionKeywords) { + int totalScoreRate = 0; + Set matchedKeywords = new HashSet<>(); + for (ExamMysqlKeyword keyword : examQuestionKeywords) { + String keywordValue = keyword.getKeyword(); + if (keywordValue != null && !keywordValue.isEmpty() && !matchedKeywords.contains(keywordValue)) { + // 使用正则,确保是完整单词(字段)匹配 + String regex = "(?i)([^\\w]|^)" + Pattern.quote(keywordValue) + "([^\\w]|$)"; + if (sql.matches(".*" + regex + ".*")) { + try { + totalScoreRate += Integer.parseInt(keyword.getScoreRate()); - - /** - * 将指定内容追加写入到指定文件中。 - * - * @param filePath 文件路径 - * @param content 要写入的内容 - */ - public static void appendToFile(String filePath, String content) { - try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) { - writer.write(content); - writer.newLine(); // 可选:添加换行符 - } catch (IOException e) { - e.printStackTrace(); + matchedKeywords.add(keywordValue); + } catch (NumberFormatException e) { + System.err.println("Invalid scoreRate format for keyword: " + keywordValue); + } + } + } } + + appendToFile(answerLogPath,"语句"+sql+"不正确,关键得分点:"+matchedKeywords+ "❌"+"关键得分"+totalScoreRate); + return totalScoreRate; } + + // 预处理函数:去除空格和换行并转为大写 + private static String normalize(String str) { + return str.replaceAll("\\s+", "").toUpperCase(); + } + public static String cleanProcedureSQL(String sql) { // 删除 DELIMITER 和 $$ 标记 sql = sql.replaceAll("(?i)DELIMITER\\s+\\$\\$", ""); // 删除 DELIMITER $$ @@ -836,33 +738,47 @@ public class MysqlServericeImpl implements IMysqlServerice { return sql.trim(); // 去除首尾空格 } + public static class DeleteInfo { + public String tableName; + public String whereClause; - - // 提取ResultSet中的结果到一个列表中 - private static List> extractResults(ResultSet resultSet) throws SQLException { - List> results = new ArrayList<>(); - - // 获取列数 - ResultSetMetaData metaData = resultSet.getMetaData(); - int columnCount = metaData.getColumnCount(); - - while (resultSet.next()) { - Map row = new HashMap<>(); - for (int i = 1; i <= columnCount; i++) { - String columnName = metaData.getColumnLabel(i); - Object value = resultSet.getObject(i); - row.put(columnName, value); - } - results.add(row); + public DeleteInfo(String tableName, String whereClause) { + this.tableName = tableName; + this.whereClause = whereClause; } - - return results; } + // 标准化 SQL 字符串 + public static String simplifyCreateTableSql(String sql) { + if (sql == null || sql.isEmpty()) return sql; + + // 移除字段中的 CHARACTER SET 和 COLLATE + sql = sql.replaceAll("(?i)CHARACTER SET\\s+\\w+", ""); + sql = sql.replaceAll("(?i)COLLATE\\s+\\w+", ""); + + // 移除主键中的 USING BTREE + sql = sql.replaceAll("(?i)USING\\s+BTREE", ""); + + // 移除表级 ENGINE、AUTO_INCREMENT、CHARSET、COLLATE、ROW_FORMAT + sql = sql.replaceAll("(?i)ENGINE\\s*=\\s*\\w+", ""); + sql = sql.replaceAll("(?i)AUTO_INCREMENT\\s*=\\s*\\d+", ""); + sql = sql.replaceAll("(?i)(DEFAULT\\s+)?CHARSET\\s*=\\s*\\w+", ""); + sql = sql.replaceAll("(?i)CHARACTER SET\\s*=\\s*\\w+", ""); + sql = sql.replaceAll("(?i)ROW_FORMAT\\s*=\\s*\\w+", ""); + sql = sql.replaceAll("(?i)COLLATE\\s*=\\s*\\w+", ""); + + // 清理多余逗号与空格 + sql = sql.replaceAll(",\\s*\\)", "\n)"); + sql = sql.replaceAll(" +", " "); + sql = sql.replaceAll("(?m)^\\s*$", ""); // 清除空行 + sql = sql.trim(); + + return sql; + } + // 比较两个结果集 private static boolean compareExtractResults(List> newResults, List> oldResults) { appendToFile(answerLogPath,"==== 标准答案 ===="); - System.out.println(""); for (Map row : newResults) { appendToFile(answerLogPath,row.toString()); } @@ -907,6 +823,28 @@ public class MysqlServericeImpl implements IMysqlServerice { } + // 提取ResultSet中的结果到一个列表中 + private static List> extractResults(ResultSet resultSet) throws SQLException { + List> results = new ArrayList<>(); + + // 获取列数 + ResultSetMetaData metaData = resultSet.getMetaData(); + int columnCount = metaData.getColumnCount(); + + while (resultSet.next()) { + Map row = new HashMap<>(); + for (int i = 1; i <= columnCount; i++) { + String columnName = metaData.getColumnLabel(i); + Object value = resultSet.getObject(i); + row.put(columnName, value); + } + results.add(row); + } + + return results; + } + + public static List extractCallStatements(String sql) { List callStatements = new ArrayList<>(); @@ -921,154 +859,6 @@ public class MysqlServericeImpl implements IMysqlServerice { } - - /** - * 比较两个查询的结果 - */ - private static boolean compareResultsSelect(List> result1, List> result2) { - // 获取列名并比较(顺序无关) - List columnNames1 = result1.get(0); - List columnNames2 = result2.get(0); - - // 检查列名是否一致(顺序无关) - Set columnSet1 = new HashSet<>(columnNames1); - Set columnSet2 = new HashSet<>(columnNames2); - if (!columnSet1.equals(columnSet2)) { - return false; - } - - // 获取数据行(去除列名) - List> rows1 = result1.subList(1, result1.size()); - List> rows2 = result2.subList(1, result2.size()); - - // 使用 Set 存储每行数据并比较 - Set> rowSet1 = new HashSet<>(); - for (List row : rows1) { - rowSet1.add(new HashSet<>(row)); - } - - Set> rowSet2 = new HashSet<>(); - for (List row : rows2) { - rowSet2.add(new HashSet<>(row)); - } - - // 比较行数据(无顺序) - return rowSet1.equals(rowSet2); - } - private static List> getAnswerList(ResultSet answer) throws SQLException { - List> result = new ArrayList<>(); - // 获取列数和列名 - ResultSetMetaData metaData = answer.getMetaData(); - int columnCount = metaData.getColumnCount(); - - // 获取列名 - List columnNames = new ArrayList<>(); - for (int i = 1; i <= columnCount; i++) { - columnNames.add(metaData.getColumnLabel(i)); - } - result.add(columnNames); // 将列名添加为结果的第一行 - - // 遍历结果集 - while (answer.next()) { - List row = new ArrayList<>(); - for (int i = 1; i <= columnCount; i++) { - row.add(answer.getString(i)); - } - result.add(row); - } - - return result; - - } - /** - * 从文件读取 SQL 语句 - */ - private static String readSQLFromFile(String filePath) throws IOException { - StringBuilder sql = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { - String line; - while ((line = reader.readLine()) != null) { - sql.append(line).append(" "); - } - } - return sql.toString().trim(); // 返回合并后的 SQL 语句 - } - - public static class DeleteInfo { - public String tableName; - public String whereClause; - - public DeleteInfo(String tableName, String whereClause) { - this.tableName = tableName; - this.whereClause = whereClause; - } - } - - /** - * 打印查询结果 - */ - private static void printResult(List> result) { - if (result.isEmpty()) { - appendToFile(answerLogPath,"查询结果为空"); - } else { - // 打印每一行数据 - for (int i = 0; i < result.size(); i++) { - List row = result.get(i); - if (i == 0) { // 打印列名 - appendToFile(answerLogPath,"列名:"); - } - for (String value : row) { - appendToFile(answerLogPath,value + "\t"); - } - System.out.println(); - } - } - } - - /** - * 执行 SQL 查询并返回结果 - */ - private static List> executeQuery(Statement stmt, String sql) throws SQLException { - List> result = new ArrayList<>(); - ResultSet rs = stmt.executeQuery(sql); - - // 获取列数和列名 - ResultSetMetaData metaData = rs.getMetaData(); - int columnCount = metaData.getColumnCount(); - - // 获取列名 - List columnNames = new ArrayList<>(); - for (int i = 1; i <= columnCount; i++) { - columnNames.add(metaData.getColumnLabel(i)); - } - result.add(columnNames); // 将列名添加为结果的第一行 - - // 遍历结果集 - while (rs.next()) { - List row = new ArrayList<>(); - for (int i = 1; i <= columnCount; i++) { - row.add(rs.getString(i)); - } - result.add(row); - } - return result; - } - /** - * 使用提供的正则表达式模式从给定的 SQL 语句中提取视图名称。 - */ - private static String extractViewName(String sql, String regex) { - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(sql); - - // 如果找到匹配项,返回匹配到的视图名称 - if (matcher.find()) { - return matcher.group(1).replace("`", ""); // 如果有反引号(`),则移除 - } else { - return "未找到视图名称"; - } - } - - /** * 比较两个查询的结果 */ @@ -1102,180 +892,232 @@ public class MysqlServericeImpl implements IMysqlServerice { // 比较行数据(无顺序) return rowSet1.equals(rowSet2); } + /** + * 执行 SQL 查询并返回结果 + */ + private static List> executeQuery(Statement stmt, String sql) throws SQLException { + List> result = new ArrayList<>(); + ResultSet rs = stmt.executeQuery(sql); + // 获取列数和列名 + ResultSetMetaData metaData = rs.getMetaData(); + int columnCount = metaData.getColumnCount(); + // 获取列名 + List columnNames = new ArrayList<>(); + for (int i = 1; i <= columnCount; i++) { + columnNames.add(metaData.getColumnLabel(i)); + } + result.add(columnNames); // 将列名添加为结果的第一行 + + // 遍历结果集 + while (rs.next()) { + List row = new ArrayList<>(); + for (int i = 1; i <= columnCount; i++) { + row.add(rs.getString(i)); + } + result.add(row); + } + return result; + } // 去除 SQL 中的注释部分 private static String removeComments(String sql) { // 正则表达式匹配 SQL 中以 -- 开头的注释 return sql.replaceAll("(?m)^[\\s]*--.*$", ""); } - public static List getAnswerView(String filePath) throws IOException { - String fileContent = new String(Files.readAllBytes(Paths.get(filePath))); + /** + * 比较两个查询的结果 + */ + private static boolean compareResultsSelect(List> result1, List> result2) { + // 获取列名并比较(顺序无关) + List columnNames1 = result1.get(0); + List columnNames2 = result2.get(0); - // 去掉换行和多余空白,方便正则识别完整语句 - fileContent = fileContent.replaceAll("[\\r\\n]+", " ").replaceAll("\\s+", " "); - - List viewStatements = new ArrayList<>(); - - // 正则表达式匹配各种形式的 CREATE VIEW - Pattern viewPattern = Pattern.compile( - "(?i)(CREATE(\\s+OR\\s+REPLACE)?(\\s+ALGORITHM\\s*=\\s*\\w+)?(\\s+DEFINER\\s*=\\s*[`\"'\\w@%\\.]+)?(\\s+SQL\\s+SECURITY\\s+\\w+)?\\s+VIEW\\b.*?;)", - Pattern.CASE_INSENSITIVE); - Matcher matcher = viewPattern.matcher(fileContent); - - while (matcher.find()) { - viewStatements.add(matcher.group(1).trim()); + // 检查列名是否一致(顺序无关) + Set columnSet1 = new HashSet<>(columnNames1); + Set columnSet2 = new HashSet<>(columnNames2); + if (!columnSet1.equals(columnSet2)) { + return false; } - return viewStatements; + // 获取数据行(去除列名) + List> rows1 = result1.subList(1, result1.size()); + List> rows2 = result2.subList(1, result2.size()); + + // 使用 Set 存储每行数据并比较 + Set> rowSet1 = new HashSet<>(); + for (List row : rows1) { + rowSet1.add(new HashSet<>(row)); + } + + Set> rowSet2 = new HashSet<>(); + for (List row : rows2) { + rowSet2.add(new HashSet<>(row)); + } + + // 比较行数据(无顺序) + return rowSet1.equals(rowSet2); } - - - - - // 根据 tableName 查找 CREATE TABLE 语句 - public static List findCreateTableStatements(Map baseData, Map newData, String tableName) { - List createStatements = new ArrayList<>(); - - // 1. 检查 newData 中是否包含 tableName - if (newData.containsKey(tableName)) { - createStatements.add(newData.get(tableName)); // 如果有,返回对应的 CREATE TABLE 语句 + /** + * 打印查询结果 + */ + private static void printResult(List> result) { + if (result.isEmpty()) { + appendToFile(answerLogPath,"查询结果为空"); } else { - // 2. 如果 newData 中没有该 tableName,比较 newData 和 baseData,找出 newData 中多出的建表语句 - for (String newTable : newData.keySet()) { - // 如果 newData 中的表在 baseData 中没有找到,说明是新增加的表 - if (!baseData.containsKey(newTable)) { - createStatements.add(newData.get(newTable)); // 将新表的 CREATE TABLE 语句加入结果列表 + // 打印每一行数据 + for (int i = 0; i < result.size(); i++) { + List row = result.get(i); + if (i == 0) { // 打印列名 + appendToFile(answerLogPath,"列名:"); } + for (String value : row) { + appendToFile(answerLogPath,value + "\t"); + } + System.out.println(); } } - - return createStatements; } - - public static String getPrimaryKeyFromSqlFile(String fileName, String tableName) { - StringBuilder sqlBuilder = new StringBuilder(); - boolean inTargetTable = false; - try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) { - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (!inTargetTable) { - // 找到对应的建表语句 - if (line.toUpperCase().startsWith("CREATE TABLE") && line.contains(tableName)) { - inTargetTable = true; - } - } else { - sqlBuilder.append(line); - - // 一般 PRIMARY KEY 会在 CREATE TABLE 块里,或者当前行 - if (line.toUpperCase().contains("PRIMARY KEY")) { - // 用正则提取主键字段名 - Pattern pattern = Pattern.compile("PRIMARY KEY\\s*\\((.*?)\\)", Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(line); - if (matcher.find()) { - String primaryKeyField = matcher.group(1).replace("`", "").trim(); - return primaryKeyField; - } - } - - // 检查建表语句是否结束 - if (line.endsWith(";")) { - inTargetTable = false; - sqlBuilder.setLength(0); // 清空,防止错误解析别的表 - } - } - } - } catch (IOException e) { - e.printStackTrace(); - } - return null; // 没找到 - } - - - - - // 解析 SQL 文件,只提取 CREATE TABLE 语句 - public static Map parseSqlFile(String fileName) { - Map tableMap = new HashMap<>(); - StringBuilder sqlBuilder = new StringBuilder(); - boolean isCreateTable = false; // 是否正在解析一个 CREATE TABLE - - try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) { - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (line.isEmpty()) { - continue; // 空行跳过 - } - - // 检查是否是 CREATE TABLE 开始 - if (line.toUpperCase().startsWith("CREATE TABLE")) { - isCreateTable = true; - sqlBuilder.setLength(0); // 清空上一次内容 - } - - if (isCreateTable) { - sqlBuilder.append(line).append(" "); // 保持空格分隔,防止黏在一起 - - // 检查是否结束了(以 COLLATE=xxx; 或 ); 结尾) - if (line.endsWith(";")) { - String sqlStatement = sqlBuilder.toString().trim(); - String tableName = extractTableName(sqlStatement); - - if (tableName != null) { - tableMap.put(tableName, sqlStatement); - } - isCreateTable = false; // 结束当前 CREATE TABLE - sqlBuilder.setLength(0); // 清空准备下一个 - } - } - } - } catch (IOException e) { - e.printStackTrace(); - } - - return tableMap; - } - - // 从 CREATE TABLE 语句中提取表名 - // 提取 CREATE TABLE 中的表名 - private static String extractTableName(String sql) { - Pattern pattern = Pattern.compile("CREATE TABLE [`\"]?(\\w+)[`\"]?", Pattern.CASE_INSENSITIVE); + /** + * 使用提供的正则表达式模式从给定的 SQL 语句中提取视图名称。 + */ + private static String extractViewName(String sql, String regex) { + Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(sql); - if (matcher.find()) { - return matcher.group(1); - } - return null; - } - // 根据 keywords 检查 insertDifferences 中是否全字段匹配并累加 scoreRate - public static int calculateTotalScoreRate(List insertDifferences, List examQuestionKeywords) { - int totalScoreRate = 0; - Set matchedKeywords = new HashSet<>(); - for (String insertSql : insertDifferences) { - for (ExamQuestionKeyword keyword : examQuestionKeywords) { - String keywordValue = keyword.getKeyword(); - if (keywordValue != null && !keywordValue.isEmpty() && !matchedKeywords.contains(keywordValue)) { - // 使用正则,确保是完整单词(字段)匹配 - String regex = "(?i)([^\\w]|^)" + Pattern.quote(keywordValue) + "([^\\w]|$)"; - if (insertSql.matches(".*" + regex + ".*")) { - try { - totalScoreRate += Integer.parseInt(keyword.getScoreRate()); - matchedKeywords.add(keywordValue); - } catch (NumberFormatException e) { - System.err.println("Invalid scoreRate format for keyword: " + keywordValue); - } + // 如果找到匹配项,返回匹配到的视图名称 + if (matcher.find()) { + return matcher.group(1).replace("`", ""); // 如果有反引号(`),则移除 + } else { + return "未找到视图名称"; + } + } + + private static List> getAnswerList(ResultSet answer) throws SQLException { + List> result = new ArrayList<>(); + // 获取列数和列名 + ResultSetMetaData metaData = answer.getMetaData(); + int columnCount = metaData.getColumnCount(); + + // 获取列名 + List columnNames = new ArrayList<>(); + for (int i = 1; i <= columnCount; i++) { + columnNames.add(metaData.getColumnLabel(i)); + } + result.add(columnNames); // 将列名添加为结果的第一行 + + // 遍历结果集 + while (answer.next()) { + List row = new ArrayList<>(); + for (int i = 1; i <= columnCount; i++) { + row.add(answer.getString(i)); + } + result.add(row); + } + + return result; + + } + + + + public static void generateInsertStatements(String tableName, Map.Entry entry, String newDbUrl, String user, String password) { + // 确保 entry 里包含的是 INSERT 语句 + if (entry.getValue().trim().toUpperCase().startsWith("INSERT")) { + System.out.println("==================插入语句=================="); + // 创建一个列表来存储所有的 INSERT INTO 语句 + List insertQueries = new ArrayList<>(); + try (Connection conn = DriverManager.getConnection(newDbUrl, user, password); + Statement stmt = conn.createStatement()) { + + // 查询表的所有列 + String columnsQuery = "DESCRIBE " + tableName; + + try (ResultSet columnsRs = stmt.executeQuery(columnsQuery)) { + List columnNames = new ArrayList<>(); + while (columnsRs.next()) { + String columnName = columnsRs.getString("Field"); + columnNames.add(columnName); } + + // 获取表的数据并生成 INSERT INTO 语句 + String selectQuery = "SELECT * FROM " + tableName; + try (ResultSet dataRs = stmt.executeQuery(selectQuery)) { + + while (dataRs.next()) { + StringBuilder insertQuery = new StringBuilder("INSERT INTO `" + tableName + "` ("); + + // 构建列名部分 + for (int i = 0; i < columnNames.size(); i++) { + insertQuery.append("`").append(columnNames.get(i)).append("`"); + if (i < columnNames.size() - 1) { + insertQuery.append(", "); + } + } + insertQuery.append(") VALUES ("); + + // 构建值部分 + for (int i = 0; i < columnNames.size(); i++) { + Object value = dataRs.getObject(columnNames.get(i)); + if (value == null) { + insertQuery.append("NULL"); + } else if (value instanceof String) { + insertQuery.append("'").append(value.toString().replace("'", "''")).append("'"); + } else { + insertQuery.append(value); + } + + if (i < columnNames.size() - 1) { + insertQuery.append(", "); + } + } + insertQuery.append(");"); + // 将生成的 INSERT INTO 语句添加到列表中 + insertQueries.add(insertQuery.toString()); + // 输出生成的 INSERT INTO 语句 + System.out.println(insertQuery.toString()); + } + + } + } + } catch (SQLException e) { + System.err.println("生成插入语句失败,表名:" + tableName); + e.printStackTrace(); + } + // 将列表赋值给 entry 的值 + entry.setValue(insertQueries.toString()); + System.out.println(entry.getValue()); + } + } + + /** + * 读取指定目录下所有文件,返回一个文件名到文件内容的键值对Map + * @param directoryPath 文件夹路径 + * @return Map<文件名, 文件内容> + * @throws IOException 读取文件异常 + */ + public static Map readFilesAsMap(String directoryPath) throws IOException { + Map fileContentMap = new HashMap<>(); + + Path dirPath = Paths.get(directoryPath); + if (!Files.isDirectory(dirPath)) { + throw new IllegalArgumentException("路径不是一个有效的目录: " + directoryPath); + } + + try (DirectoryStream stream = Files.newDirectoryStream(dirPath)) { + for (Path path : stream) { + if (Files.isRegularFile(path)) { + String fileName = path.getFileName().toString(); + String content = new String(Files.readAllBytes(path)); + fileContentMap.put(fileName, content); } } } - return totalScoreRate; + + return fileContentMap; } - - /** * 通过命令行执行 SQL 文件 */ @@ -1303,283 +1145,18 @@ public class MysqlServericeImpl implements IMysqlServerice { return false; } } - /** - * 执行其他 SQL 语句 + * 将指定内容追加写入到指定文件中。 + * + * @param filePath 文件路径 + * @param content 要写入的内容 */ - private static List executeOtherSqlStatements(List otherStatements, String dbUrl, String user, String password) throws SQLException { - Integer fileName = 1; - String outputPath = "./"; - - backupFiles.add(outputPath + "0.sql"); - - List executionResults = new ArrayList<>(); - - try (Connection conn = DriverManager.getConnection(dbUrl, user, password); - Statement stmt = conn.createStatement()) { - - for (String sql : otherStatements) { - String trimmedSql = sql.trim(); - if (!trimmedSql.isEmpty() && !trimmedSql.startsWith("--")) { - try { - stmt.executeUpdate(trimmedSql); - System.out.println("成功执行 SQL: " + trimmedSql); - - String backupFile = outputPath + fileName + ".sql"; - MySQLExporterUtil exporter = new MySQLExporterUtil(databaseName, user, password, fileName.toString()); - exporter.export(); - - backupFiles.add(backupFile); - - // 保存执行记录 - SqlExecutionResult result = new SqlExecutionResult(trimmedSql, backupFile); - executionResults.add(result); - - fileName++; - - } catch (SQLException e) { - System.err.println("执行 SQL 失败: " + trimmedSql); - e.printStackTrace(); - } - } - } - - // 所有 SQL 执行完后,反向顺序进行备份文件比较 - for (int i = backupFiles.size() - 1; i > 0; i--) { - String currentBackupFile = backupFiles.get(i); - String previousBackupFile = backupFiles.get(i - 1); - filterBackupFile(previousBackupFile, currentBackupFile); // 比较差异 - - - } - } - - System.out.println("所有 SQL 语句执行完成"); - executionResults.forEach(System.out::println); - return executionResults; - } - - // 找出两个 List 中 insert 语句的差异 - public static List findInsertDifferences(List> baseData, List> newData) { - List insertSqlList = new ArrayList<>(); // 用于存储所有新插入的 SQL 语句 - // 比较 baseData 和 newData 之间的差异 - for (Map newRecord : newData) { - boolean isNew = true; - for (Map oldRecord : baseData) { - if (oldRecord.equals(newRecord)) { - isNew = false; - break; - } - } - if (isNew) { - // 生成 INSERT 语句 - String insertSql = generateInsertSql(newRecord); - insertSqlList.add(insertSql); - } - } - return insertSqlList; // 返回包含所有新 INSERT 语句的列表 - } - - // 根据 Map 生成 INSERT 语句 - public static String generateInsertSql(Map record) { - StringBuilder columns = new StringBuilder(); - StringBuilder values = new StringBuilder(); - - for (Map.Entry entry : record.entrySet()) { - if (columns.length() > 0) { - columns.append(", "); - values.append(", "); - } - columns.append(entry.getKey()); - values.append("'").append(entry.getValue()).append("'"); - } - - return "INSERT INTO t_team (" + columns + ") VALUES (" + values + ");"; - } - private static List> parseInsertStatements(String filePath, String tableName) throws IOException { - List> dataList = new ArrayList<>(); - Pattern pattern = Pattern.compile( - "INSERT INTO\\s+" + tableName + "\\s*\\((.*?)\\)\\s*VALUES\\s*\\((.*?)\\);?", - Pattern.CASE_INSENSITIVE - ); - - try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { - StringBuilder sb = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - sb.append(line.trim()); - } - String content = sb.toString(); - Matcher matcher = pattern.matcher(content); - while (matcher.find()) { - String columns = matcher.group(1); - String values = matcher.group(2); - - String[] columnArray = columns.split(","); - String[] valueArray = values.split(","); - - Map data = new LinkedHashMap<>(); - for (int i = 0; i < columnArray.length; i++) { - data.put(columnArray[i].trim(), valueArray[i].trim().replace("'", "")); - } - dataList.add(data); - } - } - return dataList; - } - - private static List> toMap(List> dataList) { - // 直接返回原始数据列表 - return new ArrayList<>(dataList); - } - - private static List generateUpdateSql(Map oldRecord, Map newRecord, String tableName) { - List updateSqlList = new ArrayList<>(); // 用来存储多个 SQL 语句 - - StringBuilder sb = new StringBuilder(); - sb.append("UPDATE ").append(tableName).append(" SET "); - - // 存储变化字段 - List setParts = new ArrayList<>(); - List whereParts = new ArrayList<>(); - - // 遍历新记录和旧记录,检查字段变化 - for (Map.Entry entry : newRecord.entrySet()) { - String columnName = entry.getKey(); - String newValue = entry.getValue(); - String oldValue = oldRecord.get(columnName); - - // 如果值发生了变化 - if (oldValue != null && !oldValue.equals(newValue)) { - // 将变化的字段加入 SET 部分 - setParts.add(columnName + " = '" + newValue + "'"); - } - - // 始终将字段加入 WHERE 部分(无论是否变化) - whereParts.add(columnName + " = '" + oldValue + "'"); - } - - // 如果有变化的字段 - if (!setParts.isEmpty()) { - sb.append(String.join(", ", setParts)); - sb.append(" WHERE "); - sb.append(String.join(" AND ", whereParts)); - sb.append(";"); - updateSqlList.add(sb.toString()); // 将生成的 SQL 语句加入到列表 - } else { - // 没有变化的数据,可能不需要更新,视具体情况而定 - updateSqlList.add("No changes detected."); - } - - return updateSqlList; // 返回包含 SQL 语句的列表 - } - - - - - - /** - * 过滤 `backup_X.sql`,只保留与 `backup_0.sql` 不同的 SQL 语句(按 `;` 进行断句) - */ - public static void filterBackupFile(String baseFile, String newFile) { - try { - Set baseSqlSet = readSqlStatements(baseFile).stream() - .map(MysqlServericeImpl::normalizeSql) // 归一化处理空格 - .collect(Collectors.toSet()); - - List newSqlList = readSqlStatements(newFile).stream() - .filter(sql -> !baseSqlSet.contains(normalizeSql(sql))) // 归一化后再比较 - .collect(Collectors.toList()); - - try (BufferedWriter writer = new BufferedWriter(new FileWriter(newFile))) { - for (String sql : newSqlList) { - writer.write(sql + ";"); - writer.newLine(); - } - } -// System.out.println("已过滤 " + newFile + ",仅保留与 " + baseFile + " 不同的 SQL 语句"); + public static void appendToFile(String filePath, String content) { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) { + writer.write(content); + writer.newLine(); // 可选:添加换行符 } catch (IOException e) { - System.err.println("过滤文件失败:" + newFile); e.printStackTrace(); } } - - /** - * 比较备份文件与导出的数据库备份之间的差异,计算匹配比例 - */ - public static List compareBackupFiles(String exportedDatabaseFilePath, List sqlExecutionResults) { - // 读取导出的数据库备份文件并按 SQL 语句进行分割 - Set exportedSqlStatements = readSqlStatements(exportedDatabaseFilePath); - - // 遍历每个 sqlExecutionResult - for (SqlExecutionResult result : sqlExecutionResults) { - String currentFilePath = result.getBackupFile(); - - // 读取当前备份文件并按 SQL 语句进行分割 - Set currentSqlStatements = readSqlStatements(currentFilePath); - - // 输出当前备份文件中的所有 SQL 语句 -// System.out.println("文件 " + currentFilePath + " 中的 SQL 语句:"); - for (String sql : currentSqlStatements) { - System.out.println(sql); - } - - boolean allMatched = true; // 假设当前文件中所有 SQL 语句都能在总备份中找到 - - for (String currentSql : currentSqlStatements) { - String normalizedSql = normalizeSql(currentSql); - - boolean isMatched = exportedSqlStatements.stream() - .map(MysqlServericeImpl::normalizeSql) - .anyMatch(exportedSql -> exportedSql.equals(normalizedSql)); - - if (!isMatched) { - allMatched = false; -// System.out.println("未匹配的 SQL 语句: " + currentSql); - } - } - - // 根据匹配结果更新 isValid 字段 - result.setValid(allMatched); - - // 输出每条 SQL 对应的校验结果 -// System.out.println("文件 " + currentFilePath + " 的匹配结果: " + allMatched); - } - - // 返回更新过 isValid 的列表 - return sqlExecutionResults; - } - - - - /** - * 读取 SQL 文件并按 `;` 进行分割,返回去重后的 SQL 语句集合 - */ - private static Set readSqlStatements(String filePath) { - StringBuilder content = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { - String line; - while ((line = reader.readLine()) != null) { - String trimmedLine = line.trim(); - if (!trimmedLine.isEmpty() && !trimmedLine.startsWith("--")) { // 忽略空行和注释 - content.append(trimmedLine).append(" "); // 以空格拼接,防止换行影响 SQL 语句完整性 - } - } - } catch (IOException e) { - System.err.println("读取文件失败:" + filePath); - e.printStackTrace(); - } - - // 按 `;` 进行分割,并去重 - return Arrays.stream(content.toString().split(";")) - .map(String::trim) - .filter(sql -> !sql.isEmpty()) - .collect(Collectors.toSet()); - } - /** - * 标准化 SQL 语句,移除多余的空格,换行符,大小写差异 - */ - private static String normalizeSql(String sql) { - return sql.replaceAll("\\s+", " ").trim().toLowerCase(); - } -} +} \ No newline at end of file diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/utils/Mysql/SQLComparatorUtil.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/utils/Mysql/SQLComparatorUtil.java index eb142a11..6e2e313b 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/utils/Mysql/SQLComparatorUtil.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/utils/Mysql/SQLComparatorUtil.java @@ -8,6 +8,8 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * SQL 查询结果比较工具类 @@ -145,5 +147,86 @@ public class SQLComparatorUtil { // 比较行数据(无顺序) return rowSet1.equals(rowSet2); } + //比较两个udate语句 + public static boolean areUpdateStatementsEqual(String updateQuery1, String updateQuery2) { + // 1. 提取表名(忽略大小写) + String tableName1 = extractTableName(updateQuery1); + String tableName2 = extractTableName(updateQuery2); + if (tableName1 == null || tableName2 == null || !tableName1.equalsIgnoreCase(tableName2)) { + return false; + } + // 2. 提取 SET 和 WHERE 部分,移除表名前缀,统一格式 + String setPart1 = normalizeSqlPart(extractSetPart(updateQuery1), tableName1); + String setPart2 = normalizeSqlPart(extractSetPart(updateQuery2), tableName2); + + if (!setPart1.equalsIgnoreCase(setPart2)) { + return false; + } + + String wherePart1 = normalizeSqlPart(extractWherePart(updateQuery1), tableName1); + String wherePart2 = normalizeSqlPart(extractWherePart(updateQuery2), tableName2); + + return wherePart1.equalsIgnoreCase(wherePart2); + } + + // 提取表名 + private static String extractTableName(String updateQuery) { + Pattern pattern = Pattern.compile("UPDATE\\s+([a-zA-Z0-9_]+)", Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(updateQuery); + return matcher.find() ? matcher.group(1).trim() : null; + } + + // 提取 SET 子句 + private static String extractSetPart(String updateQuery) { + Pattern pattern = Pattern.compile("SET\\s+(.*?)\\s+WHERE", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + Matcher matcher = pattern.matcher(updateQuery); + return matcher.find() ? matcher.group(1).trim() : null; + } + + // 提取 WHERE 子句 + private static String extractWherePart(String updateQuery) { + Pattern pattern = Pattern.compile("WHERE\\s+(.*)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + Matcher matcher = pattern.matcher(updateQuery); + return matcher.find() ? matcher.group(1).trim() : null; + } + + // 移除表前缀和多余空格 + private static String normalizeSqlPart(String part, String tableName) { + if (part == null) return null; + return part.replaceAll("(?i)\\b" + Pattern.quote(tableName) + "\\.", "") // 去掉表名前缀 + .replaceAll("\\s+", " ") // 统一空格 + .trim(); + } + + + + + // 标准化 SQL 字符串 + public static String simplifyCreateTableSql(String sql) { + if (sql == null || sql.isEmpty()) return sql; + + // 移除字段中的 CHARACTER SET 和 COLLATE + sql = sql.replaceAll("(?i)CHARACTER SET\\s+\\w+", ""); + sql = sql.replaceAll("(?i)COLLATE\\s+\\w+", ""); + + // 移除主键中的 USING BTREE + sql = sql.replaceAll("(?i)USING\\s+BTREE", ""); + + // 移除表级 ENGINE、AUTO_INCREMENT、CHARSET、COLLATE、ROW_FORMAT + sql = sql.replaceAll("(?i)ENGINE\\s*=\\s*\\w+", ""); + sql = sql.replaceAll("(?i)AUTO_INCREMENT\\s*=\\s*\\d+", ""); + sql = sql.replaceAll("(?i)(DEFAULT\\s+)?CHARSET\\s*=\\s*\\w+", ""); + sql = sql.replaceAll("(?i)CHARACTER SET\\s*=\\s*\\w+", ""); + sql = sql.replaceAll("(?i)ROW_FORMAT\\s*=\\s*\\w+", ""); + sql = sql.replaceAll("(?i)COLLATE\\s*=\\s*\\w+", ""); + + // 清理多余逗号与空格 + sql = sql.replaceAll(",\\s*\\)", "\n)"); + sql = sql.replaceAll(" +", " "); + sql = sql.replaceAll("(?m)^\\s*$", ""); // 清除空行 + sql = sql.trim(); + + return sql; + } } diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/auto_tools/AutoToolsServiceImpl.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/auto_tools/AutoToolsServiceImpl.java index 737f9456..36b0f88e 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/auto_tools/AutoToolsServiceImpl.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/auto_tools/AutoToolsServiceImpl.java @@ -230,7 +230,6 @@ public class AutoToolsServiceImpl implements AutoToolsService{ if (cs_file_list!=null){ for (File one_file : cs_file_list) { // 6、根据试题ID查询试题详情 -// String qu_id = file.getName(); String qu_id = file.getName(); ExamQuestion examQuestion = examQuestionService.selectExamQuestionByQuId(qu_id); if (examQuestion != null) { @@ -238,29 +237,32 @@ public class AutoToolsServiceImpl implements AutoToolsService{ // --- 7.1、查询试题文件 File qu_file = new File(one_file.getPath()); File[] qu_file_list = qu_file.listFiles(); - if (qu_file_list == null) continue; + if (qu_file_list == null) continue; // --- 7.2、通过文件名称进行判分 -// for (File file_one : qu_file_list) { - // 判断名称 类似于 C语言程序设计。 课程+题型 - if (one_file.getName().split("\\.")[0].equals(examQuestion.getCourseName()+examQuestion.getSubjectName())) { - double c_score = judgementService.ProgrammingC(15.0, one_file.getPath(), one_file.getName(), examQuestion); + for (File file_one : qu_file_list) { + // 判断名称 类似于 C语言程序设计。 课程+题型 + System.out.println(one_file.getName()); + if (one_file.getName().split("\\.")[0].equals(examQuestion.getCourseName()+examQuestion.getSubjectName())) { + double c_score = judgementService.ProgrammingC(15.0, one_file.getPath(), file_one.getName(), examQuestion); score += c_score; + System.out.println(c_score+"C语言程序设计得分"); break; } // wps 类型存在多级文文件夹,需要个性化设置 - if (one_file.getName().split("\\.")[0].equals("文档")) { - double wps_word_score = judgementWpsWordService.judgementWpsWord(15.0, one_file.getPath(), one_file.getPath(), examQuestion); + if (file_one.getName().split("\\.")[0].equals("文档")) { + double wps_word_score = judgementWpsWordService.judgementWpsWord(15.0, one_file.getPath(), file_one.getPath(), examQuestion); score += wps_word_score; + System.out.println(wps_word_score+"wps得分"); break; } - // D:\1d70c404e6d42d144d0028496e893565dd2dec447f7e9b1db66466f00472424d\160\cb3cc9089b104a1e9e92deb330d0cfe8\d9f988d5ae6d435ba12d4d979d044219\stu //windows文件处理 if (one_file.getName().equals("stu")) { File win_file = new File(one_file.getPath()); double win_file_score = fileServerice.run_file_point(20.0,win_file, examQuestion); score += win_file_score; + System.out.println(win_file_score+"windows文件处理得分"); + break; } - System.out.println(one_file); //浏览器操作 // if ("浏览器网络题".equals(examQuestion.getCourseName()+examQuestion.getSubjectName())){ if (one_file.getName().equals("edge")) { @@ -268,8 +270,20 @@ public class AutoToolsServiceImpl implements AutoToolsService{ File edge_file = new File(one_file.getPath()); double browse_score= browserServerice.Judgement(20.0,edge_file,examQuestion); score += browse_score; + System.out.println(browse_score+"浏览器操作得分"); + break; } -// } + if (one_file.getName().equals("mysql")) { + System.out.println(one_file); + File mysql_file = new File(one_file.getPath()); + double judgement = mysqlServerice.Judgement(20.0,mysql_file, examQuestion); + score+=judgement; + System.out.println(judgement+"mysql得分"); + break; + } + + + } } @@ -277,15 +291,13 @@ public class AutoToolsServiceImpl implements AutoToolsService{ } } - ExamQuestion mysql=new ExamQuestion(); - double judgement = mysqlServerice.Judgement(20, mysql); - score+=judgement; + // 8、将解压之后得问及那继续重新压缩并上传到服务器,并删除文件和文件夹 String zipPath = FolderZipper.zipFolder(files[0].getPath()); // 9、上传文件 - MultipartFile file = new CustomMultipartFile(zipPath); + MultipartFile file = new CustomMultipartFile(zipPath); String path = null; - fileService.createStuFile(stuId, paperId, file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())); + fileService.createStuFile(stuId, paperId, file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())); // 10、将分数存入数据库 StuPaperScoreDO stuPaperScoreDO = new StuPaperScoreDO(); stuPaperScoreDO.setStuId(stuId);