SQLFileParser { public static void parseSQLFile(Reader stream, StatementAcceptor statements) throws Exception { StringBuilder current = new StringBuilder(); State state = State.OUT; while (true) { int _c = stream.read(); char c = (char) _c; switch (state) { case OUT: { switch (c) { case '\n': case '\r': case ';': break; case '-': state = State.SINGLELINECOMMENT_FIRSTCHAR; current.append(c); break; case '/': state = State.MULTILINECOMMENT_FIRSTCHAR; current.append(c); break; default: if (_c == EOF) { return; } state = State.INSQL; current.append(c); break; } break; } case SINGLELINECOMMENT_FIRSTCHAR: { if (c == '-') { state = State.SINGLELINECOMMENT; current.append(c); } else { throw new IOException("Unparsable SQL, found '" + c + "' after a '-'"); } break; } case MULTILINECOMMENT_FIRSTCHAR: { if (c == '*') { state = State.MULTILINECOMMENT; } else { throw new IOException("Unparsable SQL, found '" + c + "' after a '/'"); } break; } case SINGLELINECOMMENT: { if (c == '\n' || _c == EOF) { state = State.OUT; statements.accept(new Statement(current.toString(), true)); current.setLength(0); if (_c == EOF) { return; } } else { current.append(c); } break; } case MULTILINECOMMENT: { if (_c == EOF) { state = State.OUT; statements.accept(new Statement(current.toString(), true)); current.setLength(0); if (_c == EOF) { return; } } else if (c == '*') { state = State.MULTILINECOMMENT_STARTEND; current.append(c); } else { current.append(c); } break; } case MULTILINECOMMENT_STARTEND: { if (c == '/' || _c == EOF) { if (_c != EOF) { current.append(c); } state = State.OUT; statements.accept(new Statement(current.toString(), true)); current.setLength(0); } else { state = State.MULTILINECOMMENT; current.append(c); } break; } case INSQL: { if (_c == EOF) { statements.accept(new Statement(current.toString(), false)); current.setLength(0); return; } else if (c == ';') { state = State.OUT; statements.accept(new Statement(current.toString(), false)); current.setLength(0); } else if (c == '\'') { current.append(c); state = State.INSTRING; } else { current.append(c); } break; } case INSTRING: { if (_c == EOF) { throw new IllegalStateException(state + ", buffer is " + current + ". found an EOF"); } else if (c == '\'') { state = State.INSTRING_ESCAPE; current.append(c); } else if (c == '\\') { state = State.INSTRING_MYSQLESCAPE; } else { current.append(c); } break; } case INSTRING_ESCAPE: { if (_c == EOF) { throw new IllegalStateException(state + ", buffer is " + current + ". found an EOF"); } else if (c == ',' || c == ')') { current.append(c); state = State.INSQL; } else { current.append(c); state = State.INSTRING; } break; } case INSTRING_MYSQLESCAPE: { if (_c == EOF) { throw new IllegalStateException(state + ", buffer is " + current + ". found an EOF"); } else if (c == '\'') { current.append('\''); current.append(c); state = State.INSTRING; } else { current.append('\\'); current.append(c); state = State.INSTRING; } break; } default: throw new IllegalStateException(state + ", buffer is " + current); } } }  static void parseSQLFile(Reader stream, StatementAcceptor statements);  }
@Test public void testParseSQLFile() throws Exception { String sql = "-- MySQL dump 10.13 Distrib 5.6.35, for Linux (x86_64)\n" + "--\n" + "-- Host: localhost Database: seleniummonitor\n" + "-- ------------------------------------------------------\n" + "-- Server version 5.6.35\n" + "\n" + ";\n" + ";\n" + ";\n" + ";\n" + ";\n" + ";\n" + ";\n" + ";\n" + ";\n" + ";\n" + "\n" + "--\n" + "-- Table structure for table `sm_general_log`\n" + "--\n" + "\n" + "DROP TABLE IF EXISTS `sm_general_log`;\n" + ";\n" + ";\n" + "CREATE TABLE `sm_general_log` (\n" + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + " `log` varchar(2000) DEFAULT NULL,\n" + " PRIMARY KEY (`id`)\n" + ") ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;\n" + ";\n" + "\n" + "--\n" + "-- Dumping data for table `sm_general_log`\n" + "--\n" + "\n" + "LOCK TABLES `sm_general_log` WRITE;\n" + ";\n" + "INSERT INTO `sm_general_log` VALUES (2,'my string with accent '' and a semicolon;');\n" + "INSERT INTO `sm_general_log` VALUES (2,'my string with accent '' and a semicolon;');\n" + "INSERT INTO `sm_general_log` VALUES (2,'my string with accent \\' and a semicolon;');\n" + ";\n" + "UNLOCK TABLES;\n" + "\n" + "--\n" + "INSERT INTO jiraaction VALUES (24880,19803,'aaaa','comment',NULL,NULL,'backslash nella json var deve essere escaped così:\\r\\n{noformat}\\r\\n \\\\\\\\\\\\\\\\\\r\\n{noformat}\\r\\n\\r\\nperchè si trova *dentro una stringa*.\\r\\nInfatti una volta parsata la stringa il doppio \\\\\\\\ diventa \\\\','2014-07-02 12:13:38','xxxx','2014-07-02 12:13:38',NULL);\n"; List<SQLFileParser.Statement> res = new ArrayList<>(); SQLFileParser.parseSQLFile(new StringReader(sql), (s -> { if (s.comment) { System.out.println("comment: '" + s.content + "'"); } else { System.out.println("statement:'" + s.content + "'"); } res.add(s); })); }