Package org.voltdb.utils

Source Code of org.voltdb.utils.VoltTypeUtil

/* This file is part of VoltDB.
* Copyright (C) 2008-2014 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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 VoltDB.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.voltdb.utils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.logging.Logger;

import org.voltdb.VoltType;
import org.voltdb.VoltTypeException;
import org.voltdb.types.TimestampType;
import org.voltdb.types.VoltDecimalHelper;

public abstract class VoltTypeUtil {
    private static final Logger LOG = Logger.getLogger(VoltTypeUtil.class.getName());

    protected final static Random rand = new Random();
    protected static final Long DATE_STOP = System.currentTimeMillis() / 1000;
    protected static final Long DATE_START = VoltTypeUtil.DATE_STOP - 153792000;

    public static Object getRandomValue(VoltType type) {
        return getRandomValue(type, 32, 0, rand);
    }

    public static Object getRandomValue(VoltType type, int maxSize) {
        return getRandomValue(type, maxSize, 0, rand);
    }

    public static Object getRandomValue(VoltType type, int maxSize, double nullFraction, Random r) {
        assert(type != null);
        assert(maxSize >= 0);
        assert(nullFraction >= 0.0);
        assert(nullFraction <= 1.0);
        assert(r != null);

        // return null for some fraction of requests
        if (r.nextDouble() < nullFraction) {
            return null;
        }

        Object ret = null;
        switch (type) {
            // --------------------------------
            // INTEGERS
            // --------------------------------
            case TINYINT:
                ret = Byte.valueOf((byte) Math.abs(r.nextInt() % 128));
                break;
            case SMALLINT:
                ret = Short.valueOf((short) Math.abs(r.nextInt() % 32768));
                break;
            case INTEGER:
                ret = Integer.valueOf(Math.abs(r.nextInt() % 100000));
                break;
            case BIGINT:
                ret = Long.valueOf(Math.abs(r.nextInt() % 100000));
                break;
            // --------------------------------
            // FLOATS
            // --------------------------------
            case FLOAT:
                ret = Double.valueOf(Math.abs(r.nextDouble()));
                break;
            // --------------------------------
            // STRINGS
            // --------------------------------
            case STRING: {
                assert(maxSize > 0);
                int size = r.nextInt(maxSize) + 1;
                char[] str = new char[size];
                for (int ctr = 0; ctr < size; ctr++) {
                    char data = (char)(r.nextInt(128));
                    //
                    // Skip quotation marks
                    //
                    if (Character.isLetter(data) == false) {
                       ctr--;
                    } else {
                       str[ctr] = data;
                    }
                 }
                ret = new String(str);
                break;
            }
            // --------------------------------
            // VARBINARY
            // --------------------------------
            case VARBINARY: {
                assert(maxSize > 0);
                int size = r.nextInt(maxSize) + 1;
                byte[] bytestr = new byte[size];
                r.nextBytes(bytestr);
                ret = bytestr;
                break;
            }
            // --------------------------------
            // TIMESTAMP
            // --------------------------------
            case TIMESTAMP: {
                long timestamp = r.nextInt((int)(VoltTypeUtil.DATE_STOP - VoltTypeUtil.DATE_START)) + VoltTypeUtil.DATE_START;
                ret = new TimestampType(Long.valueOf(timestamp * 1000));
                break;
            }
            // --------------------------------
            // DECIMAL
            // --------------------------------
            case DECIMAL: {
                BigDecimal bd = new BigDecimal(r.nextDouble());
                ret = VoltDecimalHelper.setDefaultScale(bd);
                break;
            }
            // --------------------------------
            // INVALID
            // --------------------------------
            default:
                LOG.severe("ERROR: Unable to generate random value for invalid ValueType '" + type + "'");
        } // SWITCH
        return (ret);
    }

    private static final VoltType CAST_ORDER[] = {
        VoltType.STRING,
        VoltType.DECIMAL,
        VoltType.FLOAT,
        VoltType.TIMESTAMP,
        VoltType.BIGINT,
    };

    public static VoltType determineImplicitCasting(VoltType left, VoltType right) {
        //
        // Make sure both are valid
        //
        if (left == VoltType.INVALID || right == VoltType.INVALID) {
            throw new VoltTypeException("ERROR: Unable to determine cast type for '" + left + "' and '" + right + "' types");
        }
        // Check for NULL first, if either type is NULL the output is always NULL
        // XXX do we need to actually check for all NULL_foo types here?
        else if (left == VoltType.NULL || right == VoltType.NULL)
        {
            return VoltType.NULL;
        }
        //
        // No mixing of strings and numbers
        //
        else if ((left == VoltType.STRING && right != VoltType.STRING) ||
                (left != VoltType.STRING && right == VoltType.STRING))
        {
            throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
                                        left + "' and '" + right + "' types");
        }

        // Allow promoting INTEGER types to DECIMAL.
        else if ((left == VoltType.DECIMAL || right == VoltType.DECIMAL) &&
                !(left.isExactNumeric() && right.isExactNumeric()))
        {
            throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
                                        left + "' and '" + right + "' types");
        }
        //
        // The following list contains the rules that use for casting:
        //
        //    (1) If both types are a STRING, the output is always a STRING
        //        Note that up above we made sure that they do not mix strings and numbers
        //            Example: STRING + STRING -> STRING
        //    (2) If one type is a DECIMAL, the output is always a DECIMAL
        //        Note that above we made sure that DECIMAL only mixes with
        //        allowed types
        //    (3) Floating-point types take precedence over integers
        //            Example: FLOAT + INTEGER -> FLOAT
        //    (4) Specific types for floating-point and integer types take precedence
        //        over the more general types
        //            Example: MONEY + FLOAT -> MONEY
        //            Example: TIMESTAMP + INTEGER -> TIMESTAMP
        for (VoltType cast_type : CAST_ORDER) {
            //
            // If any one of the types is the current cast type, we'll use that
            //
            if (left == cast_type || right == cast_type)
            {
                return cast_type;
            }
        }

        // If we have INT types smaller than BIGINT
        // promote the output up to BIGINT
        if ((left == VoltType.INTEGER || left == VoltType.SMALLINT || left == VoltType.TINYINT) &&
                (right == VoltType.INTEGER || right == VoltType.SMALLINT || right == VoltType.TINYINT))
        {
            return VoltType.BIGINT;
        }

        // If we get here, we couldn't figure out what to do
        throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
                                    left + "' and '" + right + "' types");
    }

    /**
     * Returns a casted object of the input value string based on the given type
     * @throws ParseException
     */
    public static Object getObjectFromString(VoltType type, String value)
    throws ParseException
    {
        Object ret = null;
        switch (type) {
            // NOTE: All runtime integer parameters are actually Longs,so we will have problems
            // if we actually try to convert the object to one of the smaller numeric sizes

            // --------------------------------
            // INTEGERS
            // --------------------------------
            case TINYINT:
                //ret = Byte.valueOf(value);
                //break;
            case SMALLINT:
                //ret = Short.valueOf(value);
                //break;
            case INTEGER:
                //ret = Integer.valueOf(value);
                //break;
            case BIGINT:
                ret = Long.valueOf(value);
                break;
            // --------------------------------
            // FLOATS
            // --------------------------------
            case FLOAT:
                ret = Double.valueOf(value);
                break;
            // --------------------------------
            // STRINGS
            // --------------------------------
            case STRING:
                ret = value;
                break;

            case DECIMAL:
            case VARBINARY:
                if (value != null) {
                    throw new RuntimeException("Only NULL default values for DECIMAL " +
                            "and VARBINARY columns are supported right now");
                }
                break;
            // --------------------------------
            // TIMESTAMP
            // --------------------------------
            case TIMESTAMP: {
                // Support either long values (microseconds since epoch) or timestamp strings.
                try {
                    // Try to parse it as a long first.
                    ret = new TimestampType(Long.parseLong(value));
                }
                catch (NumberFormatException e) {
                    // It failed to parse as a long - parse it as a timestamp string.
                    Date date = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy").parse(value);
                    ret = new TimestampType(date.getTime() * 1000);
                }
                break;
            }
            // --------------------------------
            // INVALID
            // --------------------------------
            default:
                LOG.severe("ERROR: Unable to get object from string for invalid ValueType '" + type + "'");
        }
        return (ret);
    }

    /**
     * Get a string signature for the table represented by the args
     * @param name The name of the table
     * @param schema A sorted map of the columns in the table, keyed by column index
     * @return The table signature string.
     */
    public static String getSignatureForTable(String name, SortedMap<Integer, VoltType> schema) {
        StringBuilder sb = new StringBuilder();
        sb.append(name);
        for (VoltType t : schema.values()) {
            sb.append(t.getSignatureChar());
        }
        return sb.toString();
    }

    public static long getHashableLongFromObject(Object obj) {
        if (obj == null || VoltType.isNullVoltType(obj)) {
            return 0;
        } else if (obj instanceof Long) {
            return ((Long) obj).longValue();
        } else if (obj instanceof Integer) {
            return ((Integer)obj).intValue();
        } else if (obj instanceof Short) {
            return ((Short)obj).shortValue();
        } else if (obj instanceof Byte) {
            return ((Byte)obj).byteValue();
        } else {
            throw new RuntimeException(obj + " cannot be casted to a long");
        }
    }

    public static java.sql.Timestamp getSqlTimestampFromMicrosSinceEpoch(long timestamp) {
        java.sql.Timestamp result;

        // The lower 6 digits of the microsecond timestamp (including the "double-counted" millisecond digits)
        // must be scaled up to get the 9-digit (rounded) nanosecond value.
        if (timestamp >= 0) {
            result = new java.sql.Timestamp(timestamp/1000);
            result.setNanos(((int) (timestamp % 1000000))*1000);
        } else {
            result = new java.sql.Timestamp((timestamp/1000000 - 1) * 1000);

            int remaining = (int) (timestamp % 1000000);
            result.setNanos((remaining+1000000) * 1000 );
        }

        return result;
    }
}
TOP

Related Classes of org.voltdb.utils.VoltTypeUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.