/*
 * Copyright (C) 2006 NTT DATA Corporation
 * 
 */
package org.postgresforest.tool.util;

import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.sql.SQLException;
import java.text.DecimalFormat;

/**
 *　クエリリライタ.
 *  DDL文のテーブル名、およびインデックス名をパーティション数に応じて、変換する
 */

public class ReWriter {


	/** パーティション分割テーブルのSUFFIXフォーマット */
	protected static DecimalFormat m_dcFmt = new DecimalFormat("00");
	/**
	 * クエリリライト処理.
	 * 
	 * テーブル名を実テーブル名に変換する
	 * 
	 * @param ddl	ddl文
	 * @param tableName	テーブル名
	 * @param PatitionCount	パーティション数
	 * @return	リライトされたSQLのリスト
	 */
	static public String[] rewrite(String ddl, String tableName, int PatitionCount) {
		String[] distDdl = new String[PatitionCount];
		
		for (int i = 0; i < distDdl.length; i++) {
			distDdl[i] = ddl.replaceFirst(tableName, tableName + "_" + m_dcFmt.format(i));
			
		}
		return distDdl;		
	}
	
	/**
	 * 
	 * クエリリライト処理（CREATE INDEX版）.
	 * 
	 * テーブル名を実テーブル名に変換する。インデックス名もインデックス名_NNで変換する
	 * 
	 * @param ddl	ddl文
	 * @param indexName	インデックス名
	 * @param tableName	テーブル名
	 * @param PatitionCount	パーティション数
	 * @return	リライトされたSQLのリスト
	 */
	static public String[] rewrite(String ddl, String indexName, String tableName, int PatitionCount) {
		String[] distDdl = new String[PatitionCount];
		//インデックス名とテーブル名のリライトを" on "でsplitしたSQL文字列に対して実行
		String ddlSplit[] = ddl.split(" on ");
		for (int i = 0; i < distDdl.length; i++) {
			distDdl[i] = ddlSplit[0].replaceFirst(indexName, indexName + "_" + m_dcFmt.format(i))
						+ " on "
						+ ddlSplit[1].replaceFirst(tableName, tableName + "_" + m_dcFmt.format(i));
		}
		return distDdl;
	}
	
	/**
	 * SQL分を文字列('で囲まれた部分)以外を小文字に変換する
	 * @param sql 対象SQL文
	 * @return この時に変換されたSQL文
	 * @throws SQLException
	 */
	static public String toLowerSql(String sql) throws IOException{

		StringBuffer distSql = new StringBuffer();

		//トークナイザー取得
		StringReader fr = new StringReader(sql);
		StreamTokenizer tokenizer = new StreamTokenizer(fr);
		tokenizer.resetSyntax();
		tokenizer.wordChars('a', 'z');
		tokenizer.wordChars('A', 'Z');
		tokenizer.wordChars('_', '_');
		tokenizer.wordChars('*', '*');
		tokenizer.whitespaceChars('\t', '\t');
		tokenizer.whitespaceChars('\n', '\n');
		tokenizer.whitespaceChars('\r', '\r');
		tokenizer.eolIsSignificant(false);
		tokenizer.lowerCaseMode(true);
		tokenizer.quoteChar('\'');
		tokenizer.quoteChar('"');

		//文字列以外を小文字に変換

		int token;
		while ((token = tokenizer.nextToken()) != StreamTokenizer.TT_EOF) {
			switch (token) {
				case StreamTokenizer.TT_WORD :
					distSql.append(tokenizer.sval);
					break;
				case '\'' :
				case '"' :
					distSql.append((char)token + tokenizer.sval + (char)token);
					break;
				default :
					distSql.append((char) tokenizer.ttype);
			}
		}

		return distSql.toString();
	}
}
