All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avaje.ebean.dbmigration.DdlParser Maven / Gradle / Ivy

There is a newer version: 8.1.1
Show newest version
package com.avaje.ebean.dbmigration;

import javax.persistence.PersistenceException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

/**
 * Parses string content into separate SQL/DDL statements.
 */
public class DdlParser {

  /**
   * Break up the sql in reader into a list of statements using the semi-colon and $$ delimiters;
   */
  public List parse(StringReader reader) {

    try {
      BufferedReader br = new BufferedReader(reader);
      StatementsSeparator statements = new StatementsSeparator();

      String s;
      while ((s = br.readLine()) != null) {
        s = s.trim();
        statements.nextLine(s);
      }

      return statements.statements;

    } catch (IOException e) {
      throw new PersistenceException(e);
    }
  }


  /**
   * Local utility used to detect the end of statements / separate statements.
   * This is often just the semicolon character but for trigger/procedures this
   * detects the $$ demarcation used in the history DDL generation for MySql and
   * Postgres.
   */
  static class StatementsSeparator {

    ArrayList statements = new ArrayList();

    boolean trimDelimiter;

    boolean inDbProcedure;

    StringBuilder sb = new StringBuilder();

    void lineContainsDollars(String line) {
      if (inDbProcedure) {
        if (trimDelimiter) {
          line = line.replace("$$","");
        }
        endOfStatement(line);
      } else {
        // MySql style delimiter needs to be trimmed/removed
        trimDelimiter = line.equals("delimiter $$");
        if (!trimDelimiter) {
          sb.append(line).append(" ");
        }
      }
      inDbProcedure = !inDbProcedure;
    }

    void endOfStatement(String line) {
      // end of Db procedure
      sb.append(line);
      statements.add(sb.toString().trim());
      sb = new StringBuilder();
    }

    void nextLine(String line) {

      if (line.contains("$$")) {
        lineContainsDollars(line);
        return;
      }

      if (sb.length() == 0 && (line.isEmpty() || line.startsWith("--"))) {
        // ignore leading empty lines and sql comments
        return;
      }

      if (inDbProcedure) {
        sb.append(line).append(" ");
        return;
      }

      int semiPos = line.indexOf(';');
      if (semiPos == -1) {
        sb.append(line).append(" ");

      } else if (semiPos == line.length() - 1) {
        // semicolon at end of line
        endOfStatement(line);

      } else {
        // semicolon in middle of line
        String preSemi = line.substring(0, semiPos);
        endOfStatement(preSemi);
        sb.append(line.substring(semiPos + 1));
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy