/*
 * Copyright (C) 2005 NTT DATA Corporation
 * 
 */
package org.postgresforest.vm;

import java.io.IOException;
import java.io.StreamTokenizer;
import java.sql.SQLException;

import org.postgresforest.Driver;
import org.postgresforest.util.GT;
import org.postgresforest.util.PSQLException;
import org.postgresforest.vm.err.ForestSQLState;

/**
 * SQL構文解析クラス.
 * SQL文の構文解析の実行し、コマンドタイプを判別。
 * 各コマンドタイプにあわせて、テーブル、ＷＨＥＲＥ句（カラム−値）などを取り出す。
 * 
 *
 */

public class NoPartitionParser extends Parser{


    
    
    /**
     * @param logUtil
     */
    public NoPartitionParser(LogUtil logUtil) {
        super(logUtil);

    }
    
    
	/**
	 * コンストラクタ
	 * @param sql - SQL文
	 * @throws SQLException
	 */
	public void parse(String sql) throws SQLException{


	    init();
	    m_srcSql = sql;

	    //トークナイザーの設定
		initTokenizer(sql);


		//コマンドタイプ取得
		try {
			/*
			 * 最初に出現する文字トークンを検出する
			 */
			while( !checkToken(StreamTokenizer.TT_WORD) ){
				if(m_tokenizer.ttype == StreamTokenizer.TT_EOF) {
					break;
				}
			}
		} catch (IOException e) {
			//構文解析エラー
			throw new PSQLException(GT.tr("SQL analysis error."),ForestSQLState.INTERNAL_ERROR, e);
		}

		//Ver1.1 空のSQLに対応
		//m_type = commandSet.getInt(m_tokenizer.sval);
		if(m_tokenizer.sval != null){
			m_type = commandSet.getInt(m_tokenizer.sval);
		}

		//Ver2.1 多重化テーブルのみの場合、構文解析はコマンド解析のみ


		//コマンド別に構文解析を割り振る
		try {
			if(m_type == SELECT){
			
				parseSelect();
			
			}

			//パラメータクエリーの為に空回し。
			while(m_tokenizer.nextToken() != StreamTokenizer.TT_EOF){
			}

		} catch (IOException e1) {
			//構文解析エラー
			throw new PSQLException(GT.tr("SQL analysis error."), ForestSQLState.INTERNAL_ERROR, e1);
		}


		
		//Ver2.0 ログ追加
		if (Driver.logInfo){
			//コマンドタイプ
			switch (m_type) {
				case SELECT :
					m_logUtil.info("Parser Result: Command Type = SELECT");
					break;

				case INSERT :
					m_logUtil.info("Parser Result: Command Type = INSERT");
					break;

				case DELETE :
					m_logUtil.info("Parser Result: Command Type = DELETE");
					break;

				case UPDATE :
					m_logUtil.info("Parser Result: Command Type = UPDATE");
					break;
			}
			
			//抽出テーブル名
			String tableName = "";
			for (int i = 0; i < m_tables.size(); i++){
			    TableInfo tblInfo = (TableInfo)m_tables.get(i);
				tableName = tableName + tblInfo.getTableName() + ",";
			}
			m_logUtil.info("Parser Result: Extraction Table Name = " + tableName);

			//抽出更新カラム名
			String updateColumn = "";
			for (int i = 0; i < m_updateCol.size(); i++){
			    UpdateColumnInfo colInf = (UpdateColumnInfo)m_updateCol.get(i);
				updateColumn = updateColumn + colInf.getName() + ",";
			}
			m_logUtil.info("Parser Result: Extraction Update Column Name = " + updateColumn);
		
			//ORDER BY句
			m_logUtil.info("Parser Result: ORDER BY = " + m_orderBy);
			//GROUP BY句
			m_logUtil.info("Parser Result: GROUP BY = " + m_groupBy);
			//集約関数
			m_logUtil.info("Parser Result: FUNCTION = " + m_Function);
			//テーブル結合
			m_logUtil.info("Parser Result: JOIN = " + m_JoinTable);
			//ロックを行う
			m_logUtil.info("Parser Result: FOR UPDATE = " + m_ForUpdate);
			//DISTINCT指定
			m_logUtil.info("Parser Result: DISTINCT = " + m_distinct);
			//集合演算子（UNION,INTERSECT,EXCEPT）指定
			m_logUtil.info("Parser Result: UNION = " + m_union);
			//LIMIT指定
			m_logUtil.info("Parser Result: LIMIT = " + m_limit);
			//LIMITの指定行数
			m_logUtil.info("Parser Result: LIMIT COUNT = " + m_limitCount);
			//OFFSET指定
			m_logUtil.info("Parser Result: OFFSET = " + m_offset);
			
			//ORDER BY句の設定
			String orderName = "";
			for (int i = 0; i < m_orderList.size(); i++){
			    OrderInfo orderInfo = (OrderInfo)m_orderList.get(i);
			    orderName = orderName + orderInfo.getName() + ",";
			}
			m_logUtil.info("Parser Result: ORDER LIST = " + orderName);
			
			//GROUP BY句の設定
			String columnName = "";
			for (int i = 0; i < m_groupList.size(); i++){
				ColumnInfo columnInfo = (ColumnInfo)m_groupList.get(i);
				columnName = columnName + columnInfo.getName() + ",";
			}
			m_logUtil.info("Parser Result: GROUP LIST = " + columnName);
			
			//SELECT 出力列
			String selectColumnName = "";
			for (int i = 0; i < m_selectList.size(); i++){
				SelectColumnInfo selectColumnInfo = (SelectColumnInfo)m_selectList.get(i);
				selectColumnName = selectColumnName + selectColumnInfo.getName() + ",";
			}	
			m_logUtil.info("Parser Result: SELECT LIST = " + selectColumnName);
			
			//集約関数（集計対象）の設定
			m_logUtil.info("Parser Result: FUNCTION(TOTAL) = " + m_execFunction);
		}

		

	}

	/* (非 Javadoc)
	 * @see org.postgresforest.vm.Parser#parseSelect()
	 */
	protected void parseSelect() throws IOException, SQLException {
		int token = StreamTokenizer.TT_EOF;

		while (
			(token = m_tokenizer.nextToken()) != StreamTokenizer.TT_EOF) {

			if (token == StreamTokenizer.TT_WORD) {

				int wtype = commandSet.getInt(m_tokenizer.sval);

				String tmpSval = m_tokenizer.sval;//Vwe2.0

				switch (wtype) {


					case FOR :	//Ver1.1 FOR UPDATE
						//次にUPDATEがきたら FOR UPDATE
						if(checkToken(StreamTokenizer.TT_WORD)){
							wtype = commandSet.getInt(m_tokenizer.sval);
							if( wtype == UPDATE) {
								m_ForUpdate = true;					
								if (Driver.logDebug)
								    m_logUtil.debug("FOR UPDATE is specified！");
							}
						}
						break;


				}

			}
			//Ver3.2 コメント対応
			else if(token == '-'){	
				forwardLineComment();
			}else if(token == '/'){
				forwardComment();
			}

		}
	}

}
