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

src.com.ibm.as400.access.JDSQLTokenizer Maven / Gradle / Ivy

There is a newer version: 11.1
Show newest version
///////////////////////////////////////////////////////////////////////////////
//                                                                             
// JTOpen (IBM Toolbox for Java - OSS version)                                 
//                                                                             
// Filename: JDSQLTokenizer.java
//                                                                             
// The source code contained herein is licensed under the IBM Public License   
// Version 1.0, which has been approved by the Open Source Initiative.         
// Copyright (C) 1997-2003 International Business Machines Corporation and     
// others. All rights reserved.                                                
//                                                                             
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.access;

import java.util.*;

/**
 * This class allows SQL statements to be tokenized without having
 * to worry about delimiters appearing in comments.  The tokenizer will
 * check to make sure the delimiter is not inside a comment before using
 * it to separate tokens.  This tokenizer behaves much like StringTokenizer.
**/
class JDSQLTokenizer implements Enumeration
{
  static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";

  /**
  Constant containing the default delimiters for SQLTokenizers.
  **/
  public static final String DEFAULT_DELIMITERS = " \t\n\r\f";

  // Performance improvement when using default delimiters.
  private static final char[] INTERNAL_DELIMITERS = DEFAULT_DELIMITERS.toCharArray();

  /**
  Constant indicating the token is a delimiter.
  **/
  private static final int TOKEN_TYPE_DELIMITER = 1;

  /**
  Constant indicating the token is a comment.
  **/
  private static final int TOKEN_TYPE_COMMENT = 2;

  /**
  Constant indicating the token is a literal.
  **/
  private static final int TOKEN_TYPE_LITERAL = 4;

  /**
  Constant indicating the token is part of the SQL statement.
  **/
  private static final int TOKEN_TYPE_SQL = 8;

  private JDSQLToken[] tokens_;
  private int numberOfParameters_;

  private int currentTokenIndex_;

  /**
  Constructs a JDSQLTokenizer with the default delimiter
  String of " \t\n\r\f".

  @param  statement               SQL statement to tokenize.
  **/
  public JDSQLTokenizer(String statement)
  {
    this(statement, DEFAULT_DELIMITERS, true, true);
  }

  /**
  Constructs a JDSQLTokenizer with the specified delimiter
  String.

  @param  statement               SQL statement to tokenize.
  @param  delimiters              Set of delimiters to use.
  **/
  public JDSQLTokenizer(String statement, String delimiters)
  {
    this(statement, delimiters, true, true);
  }

  /**
  Constructs a JDSQLTokenizer with the specified delimiter String
  and the specified delimiter/comment behavior.
  
  @param statement                SQL statement to tokenize.
  @param delimiters               Set of delimiters to use.
  @param returnDelimiters         true if we should return delimiters as tokens
  @param returnComments           true if we should return comments as tokens
  **/
  public JDSQLTokenizer(String statement, String delimiters, boolean returnDelimiters, boolean returnComments)
  {
    final char[] delims = (DEFAULT_DELIMITERS.equals(delimiters) ? INTERNAL_DELIMITERS : delimiters.toCharArray());
    tokens_ = scanForTokens(statement, delims, returnComments, returnDelimiters);
    numberOfParameters_ = 0;
    for (int i=0; i 0)
        {
          final int p2 = offset+1;
          if (p2 < bufferLen)
          {
            if (buffer[offset] == '/' && buffer[p2] == '*')
            {
              ++commentDepth;
              ++offset;
            }
            else if (buffer[offset] == '*' && buffer[p2] == '/')
            {
              --commentDepth;
              ++offset;
            }
          }
          ++offset;
        }
        if (returnComments) token = new JDSQLToken(buffer, start, offset-start, TOKEN_TYPE_COMMENT);
      }
      else if (p < bufferLen && buffer[offset] == '-' && buffer[p] == '-')
      {
        // Scan for newline that ends the single-line comment.
        int start = offset;
        offset = p+1;
        while (offset < bufferLen && buffer[offset++] != '\n'){
        	//loop
        }
        if (returnComments) token = new JDSQLToken(buffer, start, offset-start, TOKEN_TYPE_COMMENT);
      }
      else if (buffer[offset] == '\'')
      {
        // entering single quote
        int start = offset;
        ++offset;
        while (offset < bufferLen && buffer[offset++] != '\'') {}
        token = new JDSQLToken(buffer, start, offset-start, TOKEN_TYPE_LITERAL);
      }
      else if (buffer[offset] == '"')
      {
        // entering double quote
        int start = offset;
        ++offset;
        while (offset < bufferLen && buffer[offset++] != '\"') {}
        token = new JDSQLToken(buffer, start, offset-start, TOKEN_TYPE_LITERAL);
      }
      else if (buffer[offset] == '(')
      { //@PDA
        // Need to check for case like "insert into x (select ...)" where there is no space after (
        // Since no select token was found, the "extended dynamic" package was not being generated. 
        // So force a token if '(' is matched.  Should be ok in all cases that are not delimited since 
        // they can have a space after '(' anyway.
        int start = offset;
        ++offset;
        token = new JDSQLToken(buffer, start, offset-start, TOKEN_TYPE_SQL);
      }
      else if (isDelimiter(buffer[offset], delimiters))
      {
        // character at pos is a delimiter
        if (returnDelimiters) token = new JDSQLToken(buffer, offset, 1, TOKEN_TYPE_DELIMITER);
        ++offset;
      }
      else
      {
        // character is not any of the above
        // scan up to the next delimiter
        int numberOfParms = 0;
        final int start = offset;
        while (offset < bufferLen &&
               !isDelimiter(buffer[offset], delimiters) &&
               buffer[offset] != '\'' &&
               buffer[offset] != '\"')
        {
          final int p2 = offset+1;
          if (p2 < bufferLen &&
              ((buffer[offset] == '/' && buffer[p2] == '*') ||
               (buffer[offset] == '-' && buffer[p2] == '-')))
          {
            break;
          }
          else if (buffer[offset] == '?')
          {
            ++numberOfParms;
          }
          ++offset;
        }
        token = new JDSQLToken(buffer, start, offset-start, TOKEN_TYPE_SQL, numberOfParms);
      }

      if (token != null) tokens.addToken(token);
    }
    final JDSQLToken[] jdTokens = new JDSQLToken[tokens.count_];
    System.arraycopy(tokens.tokens_, 0, jdTokens, 0, tokens.count_);
    return jdTokens;
  }

  /**
  Returns a list of the tokens after scanning the String, with no separators.
  
  @return The String representation of this tokenizer.
  **/
  public String toString()
  {
    StringBuffer contents = new StringBuffer();
    for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy