com.tesora.dve.sql.parser.TimestampVariableUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.sql.parser.TimestampVariableUtils.java

Source

package com.tesora.dve.sql.parser;

/*
 * #%L
 * Tesora Inc.
 * Database Virtualization Engine
 * %%
 * Copyright (C) 2011 - 2014 Tesora Inc.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */

import java.sql.Types;

import org.apache.commons.lang.StringUtils;

import com.tesora.dve.sql.node.expression.ExpressionNode;
import com.tesora.dve.sql.node.expression.FunctionCall;
import com.tesora.dve.sql.node.expression.IdentifierLiteralExpression;
import com.tesora.dve.sql.node.expression.LiteralExpression;
import com.tesora.dve.sql.schema.ConnectionContext;
import com.tesora.dve.sql.schema.PEColumn;
import com.tesora.dve.sql.schema.SchemaContext;
import com.tesora.dve.sql.statement.dml.DMLStatement;
import com.tesora.dve.sql.statement.dml.UpdateStatement;
import com.tesora.dve.sql.util.ListSet;
import com.tesora.dve.variables.KnownVariables;

/**
 * Value           Nullable    Default         On Update      Insert Set Timestamp   Update Set Timestamp
 * -----         --------   -------         ---------      --------------------   --------------------
 * null            0         0            not specified   yes (1)               yes (1)
 * null            0         0            current_ts      yes (1)               yes (1)
 * null            1          0            not specified   no                  no
 * null            1          0            current_ts      no                   no
 * null            0            not specified   not specified   yes (1)               yes (1)
 * null            0            not specified   current_ts      yes (1)               yes (1)
 * null            1            not specified   not specified   no                   no
 * null            1            not specified   current_ts      no                   no
 * null            0            literal         not specified   yes (1)               yes (1)
 * null            0            literal         current_ts      yes (1)               yes (1)
 * null            1            literal         not specified   no                   no
 * null            1            literal         current_ts      no                   no
 * null            0            current_ts      not specified   yes (1)               yes (1)
 * null            0            current_ts      current_ts      yes (1)               yes (1)
 * null            1            current_ts      not specified   no                   no
 * null            1            current_ts      current_ts      no                   no
 * null            0            null         not specified   yes (1)               yes (1)
 * null            0            null         current_ts      yes (1)               yes (1)
 * null            1            null         not specified   no                   no
 * null            1            null         current_ts      no                   no
 * 
 * literal         0         0            not specified   no                  no
 * literal         0         0            current_ts      no                  no
 * literal         1          0            not specified   no                  no
 * literal         1          0            current_ts      no                  no
 * literal         0            not specified   not specified   no                  no
 * literal         0            not specified   current_ts      no                  no
 * literal         1            not specified   not specified   no                  no
 * literal         1            not specified   current_ts      no                  no
 * literal         0            literal         not specified   no                  no
 * literal         0            literal         current_ts      no                  no
 * literal         1            literal         not specified   no                  no
 * literal         1            literal         current_ts      no                  no
 * literal         0            current_ts      not specified   no                  no
 * literal         0            current_ts      current_ts      no                  no
 * literal         1            current_ts      not specified   no                  no
 * literal         1            current_ts      current_ts      no                  no
 * literal         0            null         not specified   no                  no
 * literal         0            null         current_ts      no                  no
 * literal         1            null         not specified   no                  no
 * literal         1            null         current_ts      no                  no
 * 
 * current_ts      0         0            not specified   yes (2)               yes (2)
 * current_ts      0         0            current_ts      yes (2)               yes (2)
 * current_ts      1          0            not specified   yes (2)               yes (2)
 * current_ts      1          0            current_ts      yes (2)               yes (2)
 * current_ts      0            not specified   not specified   yes (2)               yes (2)
 * current_ts      0            not specified   current_ts      yes (2)               yes (2)
 * current_ts      1            not specified   not specified   yes (2)               yes (2)
 * current_ts      1            not specified   current_ts      yes (2)               yes (2)
 * current_ts      0            literal         not specified   yes (2)               yes (2)
 * current_ts      0            literal         current_ts      yes (2)               yes (2)
 * current_ts      1            literal         not specified   yes (2)               yes (2)
 * current_ts      1            literal         current_ts      yes (2)               yes (2)
 * current_ts      0            current_ts      not specified   yes (2)               yes (2)
 * current_ts      0            current_ts      current_ts      yes (2)               yes (2)
 * current_ts      1            current_ts      not specified   yes (2)               yes (2)
 * current_ts      1            current_ts      current_ts      yes (2)               yes (2)
 * current_ts      0            null         not specified   yes (2)               yes (2)
 * current_ts      0            null         current_ts      yes (2)               yes (2)
 * current_ts      1            null         not specified   yes (2)               yes (2)
 * current_ts      1            null         current_ts      yes (2)               yes (2)
 *     
 * not specified   0         0            not specified   no                  no (8)
 * not specified   0         0            current_ts      no                  yes (3) 
 * not specified   1          0            not specified   no                  no (8)
 * not specified   1          0            current_ts      no                  yes (3)
 * not specified   0            not specified   not specified   yes (4)               yes 
 * not specified   0            not specified   current_ts      no (6)               yes (3)
 * not specified   1            not specified   not specified   no                  no (8)
 * not specified   1            not specified   current_ts      no (6)               yes (3)
 * not specified   0            literal         not specified   no                  no (8)
 * not specified   0            literal         current_ts      no                  yes (3)
 * not specified   1            literal         not specified   no                  no (8)
 * not specified   1            literal         current_ts      no                  yes (3)
 * not specified   0            current_ts      not specified   yes                  no (8)
 * not specified   0            current_ts      current_ts      yes                  yes (3)
 * not specified   1            current_ts      not specified   yes                  no (8)
 * not specified   1            current_ts      current_ts      yes                  yes (3)
 * not specified   0            null         not specified   no (5)               no (8)
 * not specified   0            null         current_ts      no (5)               yes (3)
 * not specified   1            null         not specified   no                  no (8)
 * not specified   1            null         current_ts      no                  yes (3)
 * 
 *      
 * 1. if value is null and column is NOT nullable then mysql will insert the current timestamp.
 * 2. now() or synonyms such as current_timestamp should set current_timestamp;
 * 3. With an ON UPDATE CURRENT_TIMESTAMP clause and a constant DEFAULT clause, the column is automatically updated to the current timestamp and has the given constant default value.
 * 4. With neither DEFAULT CURRENT_TIMESTAMP nor ON UPDATE CURRENT_TIMESTAMP, it is the same as specifying both DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP
 * 5. syntax error
 * 6. With an ON UPDATE CURRENT_TIMESTAMP clause but no DEFAULT clause, the column is automatically updated to the current timestamp. The default is 0 unless the column is defined with the NULL attribute, in which case the default is NULL
 * 7. With a DEFAULT clause but no ON UPDATE CURRENT_TIMESTAMP clause, the column has the given default value and is not automatically updated to the current timestamp.
 * 8. With a constant, the default is the given value. In this case, the column has no automatic properties at all.
 *  
 */
public abstract class TimestampVariableUtils {
    public static final String TSFUNC_NOW = "now";
    public static final String TSFUNC_CURRENT_TIMESTAMP = "current_timestamp";
    public static final String TSFUNC_UNIX_TIMESTAMP = "unix_timestamp";
    public static final String TSFUNC_UTC_TIMESTAMP = "utc_timestamp";

    public static boolean setTimestampVariableForUnspecifiedColumn(SchemaContext sc, DMLStatement dmls,
            PEColumn column) {
        boolean ret = false;

        // only set the timestamp variable if this is a timestamp column
        if (column.getType().getBaseType().getDataType() != Types.TIMESTAMP) {
            return ret;
        }

        // for an update statement if the on update is set and 
        // the column is not specified then set the timestamp variable
        if ((dmls instanceof UpdateStatement) && column.isOnUpdated()) {
            ret = true;
            return ret;
        }

        boolean isNullable = column.isNullable();
        ExpressionNode defaultValue = column.getDefaultValue();
        if (defaultValue == null) {
            // no default value column modifier specified
            // now we need to know if the on update has also been set or not
            if (!column.isOnUpdated() && !isNullable) {
                // on update is not specified so default value becomes current timestamp
                ret = true;
            }
            //         else {
            //            With an ON UPDATE CURRENT_TIMESTAMP clause but no DEFAULT clause, 
            //            the column is automatically updated to the current timestamp. 
            //            The default is 0 unless the column is defined with the NULL attribute, 
            //            in which case the default is NULL.
            //         }
        } else {
            if (dmls instanceof UpdateStatement) {
                if (column.isOnUpdated()) {
                    ret = true;
                }
            } else {
                if (column.getDefaultValue() == null) {
                    // null default value
                    // do not set timestamp variable
                } else {
                    Object o = column.getDefaultValue();
                    if (o instanceof IdentifierLiteralExpression) {
                        if (StringUtils.equals(((IdentifierLiteralExpression) o).asString(sc.getValues()), "0")) {
                            // do nothing
                        } else {
                            // for a timestamp column only other choice is current_timestamp
                            ret = true;
                        }
                    } else if (o instanceof LiteralExpression) {
                        // for literal default value (ie. 0 or 'yyyy-mm-dd hh:mm:ss') 
                        // do not set timestamp variable
                    }
                }
            }
        }

        return ret;
    }

    public static boolean setTimestampVariableForSpecifiedValue(PEColumn column, ExpressionNode value) {
        boolean ret = false;

        // only set the timestamp variable if this is a timestamp column
        if (column.getType().getBaseType().getDataType() != Types.TIMESTAMP) {
            return ret;
        }

        if (value instanceof LiteralExpression) {
            if (((LiteralExpression) value).isNullLiteral()) {
                // if value is null and column is NOT nullable 
                // then mysql will insert the current timestamp.
                if (!column.isNullable()) {
                    ret = true;
                }
            } else {
                // user specified a literal (ie. 0 or 'yyyy-mm-dd hh:mm:ss') 
                // so don't set the timestamp variable
            }
        } else if (value instanceof IdentifierLiteralExpression || value instanceof FunctionCall) {
            // for a timestamp column can only be current_timestamp
            ret = true;
        }

        return ret;
    }

    public static boolean isNowFunctionCallSpecified(ListSet<FunctionCall> functions) {
        boolean usesNowFunction = false;

        if (functions == null) {
            return usesNowFunction;
        }

        for (FunctionCall fc : functions) {
            if (isTimestampFunction(fc.getFunctionName().getUnquotedName().get())) {
                usesNowFunction = true;
                break;
            }
        }

        return usesNowFunction;
    }

    public static boolean isTimestampFunction(String name) {
        return (isFunctionCurrentTimestamp(name) || isFunctionNow(name) || isFunctionUnixTimestamp(name)
                || isFunctionUTCTimestamp(name));
    }

    public static boolean isFunctionCurrentTimestamp(String name) {
        return StringUtils.equalsIgnoreCase(name, TSFUNC_CURRENT_TIMESTAMP);
    }

    public static boolean isFunctionNow(String name) {
        return StringUtils.equalsIgnoreCase(name, TSFUNC_NOW);
    }

    public static boolean isFunctionUnixTimestamp(String name) {
        return StringUtils.equalsIgnoreCase(name, TSFUNC_UNIX_TIMESTAMP);
    }

    public static boolean isFunctionUTCTimestamp(String name) {
        return StringUtils.equalsIgnoreCase(name, TSFUNC_UTC_TIMESTAMP);
    }

    /**
     * The value of 'timestamp' session variable. Can be overriden by DVE
     * 'dve_repl_slave_timestamp' variable if set to a non-zero value.
     * 
     * @return The current time in seconds.
     */
    public static long getCurrentUnixTime(ConnectionContext cc) {
        final Long replicationSlaveTimestamp = KnownVariables.REPL_TIMESTAMP.getValue(cc.getVariableSource());
        if ((replicationSlaveTimestamp != null) && (replicationSlaveTimestamp.longValue() != 0L)) {
            return replicationSlaveTimestamp;
        }

        return KnownVariables.TIMESTAMP.getValue(cc.getVariableSource());
    }

    /**
     * @return The current time in seconds.
     */
    public static long getCurrentSystemTime() {
        // we should be getting the local timezone of the mysql connection
        // but for now we will assume that the default is the same as the 
        // Java timezone
        return Long.valueOf((System.currentTimeMillis() / 1000));
    }

}