/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * 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 org.apache.openjpa.jdbc.sql;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
import org.apache.openjpa.jdbc.kernel.exps.Lit;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.schema.Index;
import org.apache.openjpa.jdbc.schema.PrimaryKey;
import org.apache.openjpa.jdbc.schema.Schema;
import org.apache.openjpa.jdbc.schema.SchemaGroup;
import org.apache.openjpa.jdbc.schema.Sequence;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.jdbc.schema.Unique;
import org.apache.openjpa.kernel.exps.Literal;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.StoreException;
import org.apache.openjpa.util.UserException;

/**
 * Dictionary for SolidDB database.
 */
public class SolidDBDictionary
    extends DBDictionary {

    /**
     * Sets whether tables are to be located in-memory or on disk.
     * Creating in-memory tables should append "STORE MEMORY" to the
     * "CREATE TABLE" statement. Creating disk-based tables should
     * append "STORE DISK". Since cursor hold over commit can not apply
     * to M-tables (which will cause SOLID Table Error 13187: The cursor
     * cannot continue accessing M-tables after the transaction has committed
     * or aborted. The statement must be re-executed.), the default is
     * STORE DISK.
     * The default concurrency control mechanism depends on the table type:
     *    Disk-based tables (D-tables) are by default optimistic.
     *    Main-memory tables (M-tables) are always pessimistic.
     * Since OpenJPA applications expects lock waits (as usually is done with
     * normal pessimistic databases), the server should be set to the pessimistic mode.
     * The optimistic mode is about not waiting for the locks at all. That increases
     * concurrency but requires more programming. The pessimistic mode with the
     * READ COMMITTED isolation level (default) should get as much concurrency as one
     * might need. The pessimistic locking mode can be set in solid.ini:
     *    [General]
     *        Pessimistic=yes
     *
     *
     */
    public boolean storeIsMemory = false;

    /**
     * If true, then simulate auto-assigned values in SolidDB by
     * using a trigger that inserts a sequence value into the
     * primary key value when a row is inserted.
     */
    public boolean useTriggersForAutoAssign = true;

    /**
     * The global sequence name to use for auto-assign simulation.
     */
    public String autoAssignSequenceName = null;

    /**
     * Flag to use OpenJPA 0.3 style naming for auto assign sequence name and
     * trigger name for backwards compatibility.
     */
    public boolean openjpa3GeneratedKeyNames = false;

    /**
     * Possible values for LockingMode are "PESSIMISTIC" and "OPTIMISTIC"
     */
    public String lockingMode = null;


    private static final Localizer _loc = Localizer.forPackage
        (SolidDBDictionary.class);

    public SolidDBDictionary() {
        platform = "SolidDB";
        bitTypeName = "TINYINT";
        blobTypeName = "LONG VARBINARY";
        booleanTypeName = "TINYINT";
        clobTypeName = "LONG VARCHAR";
        doubleTypeName = "DOUBLE PRECISION";

        allowsAliasInBulkClause = false;
        useGetStringForClobs = true;
        useSetStringForClobs = true;
        supportsDeferredConstraints = false;
        supportsNullUniqueColumn = false;

        concatenateFunction = "CONCAT({0},{1})";
        stringLengthFunction = "LENGTH({0})";
        trimLeadingFunction = "LTRIM({0})";
        trimTrailingFunction = "RTRIM({0})";
        trimBothFunction = "TRIM({0})";

        currentDateFunction = "CURDATE()";
        currentTimeFunction = "CURTIME()";
        currentTimestampFunction = "NOW()";
        lastGeneratedKeyQuery = "SELECT {0}.CURRENT";
        sequenceSQL = "SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME FROM SYS_SEQUENCES";
        sequenceSchemaSQL = "SEQSCHEMA = ?";
        sequenceNameSQL = "SEQNAME = ?";

        reservedWordSet.addAll(Arrays.asList(new String[]{
            "BIGINT", "BINARY", "DATE", "TIME",
            "TINYINT", "VARBINARY"
        }));
    }

    @Override
    public void endConfiguration() {
        super.endConfiguration();
        if (useTriggersForAutoAssign) {
            supportsAutoAssign = true;
        }
    }

    @Override
    public String[] getCreateTableSQL(Table table, SchemaGroup group) {
        StringBuilder buf = new StringBuilder();
        buf.append("CREATE TABLE ").append(getFullName(table, false)).append(" (");
        Column[] cols = table.getColumns();
        for (int i = 0; i < cols.length; i++) {
            if (i > 0)
                buf.append(", ");
            buf.append(getDeclareColumnSQL(cols[i], false));
        }

        PrimaryKey pk = table.getPrimaryKey();
        String pkStr;
        if (pk != null) {
            pkStr = getPrimaryKeyConstraintSQL(pk);
            if (!StringUtil.isEmpty(pkStr))
                buf.append(", ").append(pkStr);
        }

        Unique[] unqs = table.getUniques();
        String unqStr;
        for (Unique unq : unqs) {
            unqStr = getUniqueConstraintSQL(unq);
            if (unqStr != null)
                buf.append(", ").append(unqStr);
        }

        buf.append(") STORE ");
        if (storeIsMemory)
            buf.append("MEMORY");
        else
            buf.append("DISK");

        String[] create = null;
        if (lockingMode != null) {
            StringBuilder buf1 = new StringBuilder();
            if (lockingMode.equalsIgnoreCase("PESSIMISTIC")) {
                buf1.append("ALTER TABLE ").append(getFullName(table, false)).
                    append(" SET PESSIMISTIC");
            } else if (lockingMode.equalsIgnoreCase("OPTIMISTIC")){
                buf1.append("ALTER TABLE ").append(getFullName(table, false)).
                    append(" SET OPTIMISTIC");
            } else
                throw new UserException(_loc.get("invalid-locking-mode", lockingMode));

            create = new String[2];
            create[0] = buf.toString();
            create[1] = buf1.toString();
        } else {
            create = new String[1];
            create[0] = buf.toString();
        }

        if (!useTriggersForAutoAssign)
            return create;

        List seqs = null;
        String seq, trig;
        for (int i = 0; cols != null && i < cols.length; i++) {
            if (!cols[i].isAutoAssigned())
                continue;
            if (seqs == null)
                seqs = new ArrayList(4);

            seq = getAutoGenSeqName(cols[i]);
            if (sequenceExists(table.getSchemaIdentifier().getName(), seq, group))
                seqs.add("DROP SEQUENCE " + seq);
            seqs.add("CREATE SEQUENCE " + seq);

            if (openjpa3GeneratedKeyNames)
                trig = getOpenJPA3GeneratedKeyTriggerName(cols[i]);
            else
                trig = getGeneratedKeyTriggerName(cols[i]);

            // create the trigger that will insert new values into
            // the table whenever a row is created
            // CREATE TRIGGER TRIG01 ON table1
            //     BEFORE INSERT
            //     REFERENCING NEW COL1 AS NEW_COL1
            // BEGIN
            //     EXEC SEQUENCE seq1 NEXT INTO NEW_COL1;
            // END;

            seqs.add("CREATE TRIGGER " + trig
                + " ON " + toDBName(table.getIdentifier())
                + " BEFORE INSERT REFERENCING NEW " + toDBName(cols[i].getIdentifier())
                + " AS NEW_COL1 BEGIN EXEC SEQUENCE " + seq + " NEXT INTO NEW_COL1; END");

        }
        if (seqs == null)
            return create;

        // combine create table sql and create sequences sql
        String[] sql = new String[create.length + seqs.size()];
        System.arraycopy(create, 0, sql, 0, create.length);
        for (int i = 0; i < seqs.size(); i++)
            sql[create.length + i] = (String) seqs.get(i);
        return sql;
    }

    protected boolean sequenceExists(String schemaName, String seqName, SchemaGroup group) {
        Schema[] schemas = group.getSchemas();
        for (Schema schema : schemas) {
            String dbSchemaName = schema.getIdentifier().getName();
            if (schemaName != null && !schemaName.equalsIgnoreCase(dbSchemaName))
                continue;

            Sequence[] seqs = schema.getSequences();
            for (Sequence seq : seqs) {
                String dbSeqName = seq.getName();
                if (dbSeqName != null && dbSeqName.equalsIgnoreCase(seqName))
                    return true;
            }
        }
        return false;
    }

    /**
     * Trigger name for simulating auto-assign values on the given column.
     */
    protected String getGeneratedKeyTriggerName(Column col) {
        // replace trailing _SEQ with _TRG
        String seqName = getGeneratedKeySequenceName(col);
        return seqName.substring(0, seqName.length() - 3) + "TRG";
    }

    /**
     * Returns a OpenJPA 3-compatible name for an auto-assign sequence.
     */
    protected String getOpenJPA3GeneratedKeySequenceName(Column col) {
        Table table = col.getTable();
        DBIdentifier sName = DBIdentifier.preCombine(table.getIdentifier(), "SEQ");
        return toDBName(getNamingUtil().makeIdentifierValid(sName, table.getSchema().
            getSchemaGroup(), maxTableNameLength, true));
    }

    /**
     * Returns a OpenJPA 3-compatible name for an auto-assign trigger.
     */
    protected String getOpenJPA3GeneratedKeyTriggerName(Column col) {
        Table table = col.getTable();
        DBIdentifier sName = DBIdentifier.preCombine(table.getIdentifier(), "TRIG");
        return toDBName(getNamingUtil().makeIdentifierValid(sName, table.getSchema().
            getSchemaGroup(), maxTableNameLength, true));
    }

    protected String getAutoGenSeqName(Column col) {
        String seqName = autoAssignSequenceName;
        if (seqName == null) {
            if (openjpa3GeneratedKeyNames)
                seqName = getOpenJPA3GeneratedKeySequenceName(col);
            else
                seqName = getGeneratedKeySequenceName(col);
        }
        return seqName;
    }

    @Override
    protected String getGenKeySeqName(String query, Column col) {
        return MessageFormat.format(query, new Object[]{getAutoGenSeqName(col)});
    }

    @Override
    public String convertSchemaCase(DBIdentifier objectName) {
        if (objectName != null && objectName.getName() == null)
            return "";
        return super.convertSchemaCase(objectName);
    }

    @Override
    public void substring(SQLBuffer buf, FilterValue str, FilterValue start,
            FilterValue length) {
        if (length != null) {
            super.substring(buf, str, start, length);
        } else {
            buf.append(substringFunctionName).append("(");
            str.appendTo(buf);
            buf.append(", ");
            if (start.getValue() instanceof Number) {
                buf.append(Long.toString(toLong(start)));
            } else {
                start.appendTo(buf);
            }
            buf.append(", ");
            if (start.getValue() instanceof Number) {
                long startLong = toLong(start);
                long endLong = Integer.MAX_VALUE; //2G
                buf.append(Long.toString(endLong - startLong));
            } else {
                buf.append(Integer.toString(Integer.MAX_VALUE));
                buf.append(" - (");
                start.appendTo(buf);
                buf.append(")");
            }
            buf.append(")");
        }
    }

    @Override
    public void indexOf(SQLBuffer buf, FilterValue str, FilterValue find,
        FilterValue start) {
        buf.append("LOCATE(");
        find.appendTo(buf);
        buf.append(", ");
        str.appendTo(buf);
        if (start != null) {
            buf.append(", ");
            start.appendTo(buf);
        }
        buf.append(")");
    }

    @Override
    public boolean isSystemIndex(DBIdentifier name, Table table) {
        // names starting with "$$" are reserved for SolidDB internal use
        String strName = DBIdentifier.isNull(name) ? null : name.getName();
        boolean startsWith$$ = false;
        if (strName != null) {
            startsWith$$ = name.isDelimited() ? strName.startsWith("\"$$") :
                strName.startsWith("$$");
        }
        return super.isSystemIndex(name, table) || startsWith$$;
    }

    @Override
    public boolean isSystemSequence(DBIdentifier name, DBIdentifier schema,
            boolean targetSchema) {
        if (super.isSystemSequence(name, schema, targetSchema))
            return true;
        String schemaName = DBIdentifier.isNull(schema) ? null : schema.getName();
        boolean startsWith_SYSTEM = schema.isDelimited() ? schemaName.startsWith("\"_SYSTEM") :
            schemaName.startsWith("_SYSTEM");

        String seqName = DBIdentifier.isNull(name) ? null : name.getName();
        boolean startsWithSYS_SEQ_ = name.isDelimited() ? seqName.startsWith("\"SYS_SEQ_") :
            seqName.startsWith("SYS_SEQ_");
        if (startsWith_SYSTEM && startsWithSYS_SEQ_)
            return true;
        return false;
    }

    @Override
    public void setBigDecimal(PreparedStatement stmnt, int idx, BigDecimal val,
            Column col) throws SQLException {
        int type = (val == null || col == null) ? JavaTypes.BIGDECIMAL
                : col.getJavaType();
        switch (type) {
        case JavaTypes.DOUBLE:
        case JavaTypes.DOUBLE_OBJ:
            setDouble(stmnt, idx, val.doubleValue(), col);
            break;
        case JavaTypes.FLOAT:
        case JavaTypes.FLOAT_OBJ:
            setFloat(stmnt, idx, val.floatValue(), col);
            break;
        case JavaTypes.LONG:
        case JavaTypes.LONG_OBJ:
            setLong(stmnt, idx, val.longValue(), col);
            break;
        default:
            super.setBigDecimal(stmnt, idx, val, col);
        }
    }

    @Override
    public void setDouble(PreparedStatement stmnt, int idx, double val,
            Column col) throws SQLException {
        int type = (col == null) ? JavaTypes.DOUBLE
                : col.getJavaType();
        switch (type) {
        case JavaTypes.DOUBLE:
        case JavaTypes.DOUBLE_OBJ:
            super.setDouble(stmnt, idx, val, col);
            break;
        case JavaTypes.FLOAT:
        case JavaTypes.FLOAT_OBJ:
            setFloat(stmnt, idx, Double.valueOf(val).floatValue(), col);
            break;
        case JavaTypes.LONG:
        case JavaTypes.LONG_OBJ:
            setLong(stmnt, idx, Double.valueOf(val).longValue(), col);
            break;
        }
    }

    @Override
    public boolean needsToCreateIndex(Index idx, Table table, Unique[] uniques) {
       // SolidDB will automatically create a unique index for the
       // constraint, so don't create another index again
       PrimaryKey pk = table.getPrimaryKey();
       if (pk != null && idx.columnsMatch(pk.getColumns()))
           return false;

       // If table1 has constraints on column (a, b), an explicit index on (a)
       // will cause duplicate index error from SolidDB
       Column[] icols = idx.getColumns();
       boolean isDuplicate = false;
       boolean mayBeDuplicate = false;
        for (Unique unique : uniques) {
            Column[] ucols = unique.getColumns();
            if (ucols.length < icols.length)
                continue;
            for (int j = 0, k = 0; j < ucols.length && k < icols.length; j++, k++) {
                if (mayBeDuplicate && ucols[j].getQualifiedPath().equals(icols[k].getQualifiedPath())) {
                    if (k == icols.length - 1) {
                        isDuplicate = true;
                    }
                    else {
                        mayBeDuplicate = true;
                    }
                }
                else
                    mayBeDuplicate = false;
            }
            if (isDuplicate)
                break;
        }
       return isDuplicate;
    }

    @Override
    protected String getSequencesSQL(String schemaName, String sequenceName) {
        return getSequencesSQL(DBIdentifier.newSchema(schemaName),
            DBIdentifier.newSequence(sequenceName));
    }

    @Override
    protected String getSequencesSQL(DBIdentifier schemaName, DBIdentifier sequenceName) {
        StringBuilder buf = new StringBuilder();
        buf.append(sequenceSQL);
        if (!DBIdentifier.isNull(schemaName) || !DBIdentifier.isNull(sequenceName))
            buf.append(" WHERE ");
        if (!DBIdentifier.isNull(schemaName)) {
            buf.append(sequenceSchemaSQL);
            if (!DBIdentifier.isNull(sequenceName))
                buf.append(" AND ");
        }
        if (!DBIdentifier.isNull(sequenceName))
            buf.append(sequenceNameSQL);
        return buf.toString();
    }

    @Override
    protected void appendSelect(SQLBuffer selectSQL, Object alias, Select sel,
            int idx) {
        // if this is a literal value, add a cast...
        Object val = sel.getSelects().get(idx);
        boolean toCast = (val instanceof Lit) &&
        ((Lit)val).getParseType() != Literal.TYPE_DATE &&
        ((Lit)val).getParseType() != Literal.TYPE_TIME &&
        ((Lit)val).getParseType() != Literal.TYPE_TIMESTAMP;

        if (toCast)
            selectSQL.append("CAST(");

            // ... and add the select per super's behavior...
        super.appendSelect(selectSQL, alias, sel, idx);

        // ... and finish the cast
        if (toCast) {
            Class c = ((Lit) val).getType();
            int javaTypeCode = JavaTypes.getTypeCode(c);
            int jdbcTypeCode = getJDBCType(javaTypeCode, false);
            String typeName = getTypeName(jdbcTypeCode);
            selectSQL.append(" AS " + typeName);

            // if the literal is a string, use the default char col size
            // in the cast statement.
            if (String.class.equals(c))
                selectSQL.append("(" + characterColumnSize + ")");

            selectSQL.append(")");
        }
    }

    /**
     * Solid does not support deferred referential integrity checking.
     */
    @Override
    protected ForeignKey newForeignKey(ResultSet fkMeta)
    throws SQLException {
        ForeignKey fk = super.newForeignKey(fkMeta);
        fk.setDeferred(false);
        return fk;
    }

    @Override
    public boolean isFatalException(int subtype, SQLException ex) {
        String errorState = ex.getSQLState();
        int errorCode = ex.getErrorCode();
        if (subtype == StoreException.LOCK && errorCode == 14529 && "HY000".equals(errorState))
            return false;
        return super.isFatalException(subtype, ex);
    }
}
