/*
 * 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.oracle;

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.EQLReqFrom;
import com.queplix.core.modules.eql.EQLReqSelectAttr;
import com.queplix.core.modules.eql.EQLStringObject;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.eql.funcs.DateDiffFunc;
import com.queplix.core.modules.eql.funcs.FTSFunc;
import com.queplix.core.modules.eql.funcs.IsNullFunc;
import com.queplix.core.modules.eql.parser.generic.SQLSelectBuilderGenericImpl;

/**
 * <p>Select SQL builder ORACLE 9i implementation</p>
 *
 * @author Baranov Andrey [ALB]
 * @version $Revision: 1.1.1.1 $ $Date: 2005/09/12 15:30:32 $
 */

public class SQLSelectBuilderOracleImpl
        extends SQLSelectBuilderGenericImpl {

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

        EQLReqFrom reqFrom = req.getFrom();
        int fromSize = reqFrom.fromSize();

        if(fromSize > 0) {
            super.addFromClause();
        } else {
            fromClause.append("DUAL");
        }
    }

    /*
     * No javadoc
     * @see SQLBuilderGenericImpl#getSQLOperandMember
     */
    protected String getSQLOperandMember(FTSFunc memberField)
            throws EQLException {

        String fieldName = getSQLOperand(memberField.getParameter(0));
        String ftsStr = getSQLValue((EQLStringObject) memberField.getParameter(
                1).getSubOp(0).getMember());

        /** @todo write parser for FTS search string */

        return "contains(" + fieldName + "," + ftsStr + ") > 0";
    }

    /*
     * (No javadoc)
     * @see SQLSelectBuilderGenericImpl#getSQLColumnSelect
     */
    protected String getSQLColumnSelect(EQLReq req,
                                        EQLReqSelectAttr reqSelectAttr)
            throws EQLException {

        Efield field = reqSelectAttr.getReqField().getField();
        int sql_type = field.getSqltype().getType();
        boolean isLazy = req.isLazy(field);
        boolean isDistinct = req.getSelect().isDistinct();

        if(sql_type == SqlSType.MEMO_LONG_TYPE) {
            return super.getSQLColumnSelect(req, reqSelectAttr);
        }
        if(sql_type == SqlSType.MEMO_TYPE) {
            if(isLazy) {
                // Add DBMS_LOB.GETLENGTH() for MEMO
                String sqlColumnName = getSQLOperand(reqSelectAttr.getReqOp());
                return "DBMS_LOB.GETLENGTH(" + sqlColumnName + ")";
            } else if(isDistinct) {
                // Add DATALENGTH() and TEXTPTR()
                String sqlColumnName = getSQLOperand(reqSelectAttr.getReqOp());
                StringBuffer sql = new StringBuffer();
                sql.append("DBMS_LOB.GETLENGTH(").append(sqlColumnName).append(
                        ")");
                sql.append(",");
                sql.append(" NULL");
                //sql.append( "TEXTPTR(" ).append( sqlColumnName ).append( ")" );
                return sql.toString();
            }
        } else if(sql_type == SqlSType.BINARY_TYPE) {


            if(isLazy) {
                // Add DBMS_LOB.GETLENGTH() for BINARY
                String sqlColumnName = getSQLOperand(reqSelectAttr.getReqOp());
                return "DBMS_LOB.GETLENGTH(" + sqlColumnName + ")";

            } else if(isDistinct) {
                // Not supported!
                throw new IllegalStateException(
                        "Binary fields not supported with DISTINCT");
            }

        } else if(isLazy) {
            if(!field.getVirtual().booleanValue()) {
                // Use CASE expression for none-virtual fields
                String sqlColumnName = getSQLOperand(reqSelectAttr.getReqOp());
                return "(CASE WHEN " + sqlColumnName
                        + " IS NULL THEN 0 ELSE 1 END)";
            } else {
                // Field is vitual - always return '1'
                return "1";
            }
        }

        // Return default column
        return super.getSQLColumnSelect(req, reqSelectAttr);
    }

    protected String getSQLOperandMember(DateDiffFunc memberField)
            throws EQLException {
        return getSQLOperand(memberField.getParameter(1)) + " - "
                + getSQLOperand(memberField.getParameter(0));
    }

    protected String getSQLOperandMember(IsNullFunc memberField)
            throws EQLException {
        return "Nvl(" + getSQLOperand(memberField.getParameter(0)) + ","
                + getSQLOperand(memberField.getParameter(1)) + ")";
    }

}
