/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

package com.queplix.core.modules.eql.parser.db2;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.jxb.entity.Efield;
import com.queplix.core.jxb.entity.types.SqlSType;
import com.queplix.core.modules.eql.EQLReq;
import com.queplix.core.modules.eql.EQLReqEntity;
import com.queplix.core.modules.eql.EQLReqField;
import com.queplix.core.modules.eql.EQLReqSelectAttr;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.eql.funcs.FTSFunc;
import com.queplix.core.modules.eql.funcs.LowerFunc;
import com.queplix.core.modules.eql.funcs.UpperFunc;
import com.queplix.core.modules.eql.parser.generic.SQLSelectBuilderGenericImpl;
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;

/**
 * <p>Select SQL builder DB2 implementation</p>
 *
 * @author Timofei Nevolin [TN]
 * @author Andrey Baranov [ALB]
 * @version $Revision: 1.1.1.1 $ $Date: 2005/09/12 15:30:28 $
 */

public class SQLSelectBuilderDB2Impl
        extends SQLSelectBuilderGenericImpl {

    /*
     * (No javadoc)
     * @see SQLBuilderGenericImpl#getCountSql
     */
    protected String getCountSql(String mainSql)
            throws EQLException {
        try {
            // remove <ORDER BY> tail
            RE re = new RE("order[ \t\n\r]+by", RE.MATCH_CASEINDEPENDENT);
            if(re.match(mainSql)) {
                mainSql = mainSql.substring(0, re.getParenStart(0));
            }

        } catch (RESyntaxException ex) {
            throw new GenericSystemException(ex);
        }

        return "SELECT COUNT(*) FROM (" + mainSql + ") REQ";
    }

    /*
     * (No javadoc)
     * @see SQLBuilderGenericImpl#addFromClause
     */
    protected void addFromClause()
            throws EQLException {

        if(req.getFrom().fromSize() == 0) {
            // add dummy table if no any phys. tables found
            fromClause.append("sysibm.sysdummy1");
        } else {
            super.addFromClause();
        }
    }

    /*
     * No javadoc
     * @see SQLBuilderGenericImpl#getSQLFieldSelect
     */
    protected String getSQLFieldSelect(EQLReq req,
                                       EQLReqSelectAttr reqSelectAttr, int i)
            throws EQLException {

        StringBuffer sql = new StringBuffer();
        Efield field = reqSelectAttr.getReqField().getField();
        int sql_type = field.getSqltype().getType();

        // Check if field lazy

        boolean isLazy = req.isLazy(field);
        if(isLazy) {
            if(sql_type == SqlSType.MEMO_TYPE) {
                // add LENGTH() for MEMO
                String sqlColumnName = getSQLOperand(reqSelectAttr.getReqOp());
                sql.append("LENGTH(").append(sqlColumnName).append(
                        ") AS LAZYFIELD").append(i);
            } else {
                // add '1' for the rest
                sql.append("1 AS LAZYFIELD").append(i);
            }
            return sql.toString();
        }

        // Return default column

        return super.getSQLFieldSelect(req, reqSelectAttr, i);
    }

    /*
     * No javadoc
     * @see SQLBuilderGenericImpl#getSQLOperandMember(FTSFunc)
     */
    protected String getSQLOperandMember(FTSFunc memberField)
            throws EQLException {
        throw new UnsupportedOperationException();
    }

    /*
     * No javaodc
     * @see SQLBuilder#getSQLColumnName(EQLReqField)
     */
    protected String getSQLColumnName(EQLReqField reqField) {
        EQLReqEntity reqEntity = reqField.getReqEntity();
        Efield field = reqField.getField();
        return getDbAlias(reqEntity) + ".\"" + field.getName().toUpperCase()
                + "\"";
    }

    /*
     * No javaodc
     * @see SQLBuilder#getSQLOperandMember(LowerFunc)
     */
    protected String getSQLOperandMember(LowerFunc memberField)
            throws EQLException {

        String operand = getSQLOperand(memberField.getParameter(0));
        if(operand.equals("?")) {
            // .. only varchar(N) supported
            int n = getLastSqlParameter().toString().length();
            return "LOWER(CAST(? AS VARCHAR(" + n + ")))";
        } else {
            return "LOWER(" + operand + ")";
        }
    }

    /*
     * No javaodc
     * @see SQLBuilder#getSQLOperandMember(UpperFunc)
     */
    protected String getSQLOperandMember(UpperFunc memberField)
            throws EQLException {

        String operand = getSQLOperand(memberField.getParameter(0));
        if(operand.equals("?")) {
            // .. only varchar(N) supported
            int n = getLastSqlParameter().toString().length();
            return "UPPER(CAST(? AS VARCHAR(" + n + ")))";
        } else {
            return "UPPER(" + operand + ")";
        }
    }
}
