View Javadoc

1   package org.codehaus.mojo.sql;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.codehaus.plexus.util.StringUtils;
23  
24  /**
25   * Utility class to split a long sql batch script into single SQL commands.
26   */
27  public class SqlSplitter {
28      /**
29       * Value indicating the sql has no end-delimiter like i.e. semicolon
30       */
31      public static final int NO_END = -1;
32  
33      /**
34       * Check if the given sql line contains an end of command ';' Please note that we do <em>not</em> fully parse the
35       * SQL, so if we get a malformed statement, we cannot detect it.
36       *
37       * @param line
38       *            to parse
39       * @param delimiter
40       *            which should be used to split SQL commands
41       * @return position after the end character if the given line contains the end of a SQL script,
42       *         {@value SqlSplitter#NO_END} if it doesn't contain an end char.
43       */
44      public static int containsSqlEnd(String line, String delimiter) {
45          // / * * / comments
46          boolean isComment = false;
47  
48          boolean isAlphaDelimiter = StringUtils.isAlpha(delimiter);
49  
50          if (line == null || line.length() == 0) {
51              return NO_END;
52          }
53  
54          int pos = 0;
55  
56          do {
57              if (isComment) {
58                  if (line.startsWith("*/", pos)) {
59                      isComment = false;
60                  } else {
61                      pos++;
62                      continue;
63                  }
64              }
65  
66              if (line.startsWith("/*", pos)) {
67                  isComment = true;
68                  pos += 2;
69                  continue;
70              }
71  
72              if (line.startsWith("--", pos)) {
73                  return NO_END;
74              }
75  
76              if (line.startsWith("'", pos) || line.startsWith("\"", pos)) {
77                  String quoteChar = "" + line.charAt(pos);
78                  String quoteEscape = "\\" + quoteChar;
79                  pos++;
80  
81                  if (line.length() <= pos) {
82                      return NO_END;
83                  }
84  
85                  do {
86                      if (line.startsWith(quoteEscape, pos)) {
87                          pos += 2;
88                      }
89                  } while (!line.startsWith(quoteChar, pos++));
90  
91                  continue;
92              }
93  
94              if (line.startsWith(delimiter, pos)) {
95                  if (isAlphaDelimiter) {
96                      // check if delimiter is at start or end of line, surrounded
97                      // by non-alpha character
98                      if ((pos == 0 || !isAlpha(line.charAt(pos - 1)))
99                              && (line.length() == pos + delimiter.length() || !isAlpha(line.charAt(pos
100                                     + delimiter.length())))) {
101                         return pos + delimiter.length();
102                     }
103                 } else {
104                     return pos + delimiter.length();
105                 }
106             }
107 
108             pos++;
109 
110         } while (line.length() >= pos);
111 
112         return NO_END;
113     }
114 
115     /**
116      * @param c
117      *            the char to check
118      * @return <code>true</code> if the given character is either a lower or an upperchase alphanumerical character
119      */
120     private static boolean isAlpha(char c) {
121         return Character.isUpperCase(c) || Character.isLowerCase(c);
122     }
123 
124 }