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      /**
30       * Value indicating the sql has no end-delimiter like i.e. semicolon
31       */
32      public static final  int NO_END = -1; 
33      
34      /**
35       * Check if the given sql line contains an end of command ';'
36       * Please note that we do <em>not</em> fully parse the SQL, 
37       * so if we get a malformed statement, we cannot detect it.
38       * 
39       * @param line to parse
40       * @param delimiter 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      {
46          // / * * / comments
47          boolean isComment = false;
48          
49          boolean isAlphaDelimiter = StringUtils.isAlpha( delimiter );
50          
51          if ( line == null || line.length() == 0 )
52          {
53              return NO_END;
54          }
55          
56          int pos = 0;
57          
58          do 
59          {
60              if ( isComment )
61              {
62                  if ( line.startsWith( "*/", pos ) )
63                  {
64                      isComment = false;
65                  }
66                  else
67                  {
68                      pos++;
69                      continue;
70                  }
71              }
72              
73              if ( line.startsWith( "/*", pos ) )
74              {
75                  isComment = true;
76                  pos += 2;
77                  continue;
78              }
79              
80              if ( line.startsWith( "--", pos ) )
81              {
82                  return NO_END;
83              }
84              
85              if (  line.startsWith( "'", pos ) || line.startsWith( "\"", pos ) )
86              {
87                  String quoteChar = "" + line.charAt( pos );
88                  String quoteEscape = "\\" + quoteChar;
89                  pos++;
90                  
91                  if ( line.length() <= pos )
92                  {
93                      return NO_END;
94                  }
95                  
96                  do 
97                  {
98                      if ( line.startsWith( quoteEscape, pos ) )
99                      {
100                         pos += 2;
101                     }
102                 } while ( !line.startsWith( quoteChar, pos++ ) );
103                 
104                 continue;
105             }
106 
107             if ( line.startsWith( delimiter, pos ) )
108             {
109                 if ( isAlphaDelimiter )
110                 {
111                     // check if delimiter is at start or end of line, surrounded
112                     // by non-alpha character
113                     if (  ( pos == 0 || !isAlpha( line.charAt( pos - 1 ) ) ) 
114                                     && ( line.length() == pos + delimiter.length() 
115                                     || !isAlpha( line.charAt( pos + delimiter.length() ) ) ) ) 
116                     {
117                         return pos + delimiter.length();
118                     }
119                 }
120                 else
121                 {
122                     return pos + delimiter.length();
123                 }
124             }
125             
126             pos++;
127             
128         } while ( line.length() >= pos );
129             
130         return NO_END;
131     }
132     
133     /**
134      * @param c the char to check
135      * @return <code>true</code> if the given character is either a lower or an upperchase alphanumerical character
136      */
137     private static boolean isAlpha( char c )
138     {
139         return Character.isUpperCase( c ) || Character.isLowerCase( c );
140     }
141     
142 }