Package com.foundationdb.server.types.mcompat.mfuncs

Source Code of com.foundationdb.server.types.mcompat.mfuncs.MExtractField

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.server.types.mcompat.mfuncs;

import com.foundationdb.server.error.InvalidDateFormatException;
import com.foundationdb.server.error.InvalidParameterValueException;
import com.foundationdb.server.types.LazyList;
import com.foundationdb.server.types.TClass;
import com.foundationdb.server.types.TExecutionContext;
import com.foundationdb.server.types.TScalar;
import com.foundationdb.server.types.TOverloadResult;
import com.foundationdb.server.types.mcompat.mtypes.MDateAndTime;
import com.foundationdb.server.types.mcompat.mtypes.MNumeric;
import com.foundationdb.server.types.mcompat.mtypes.MString;
import com.foundationdb.server.types.value.ValueSource;
import com.foundationdb.server.types.value.ValueTarget;
import com.foundationdb.server.types.texpressions.TInputSetBuilder;
import com.foundationdb.server.types.texpressions.TScalarBase;

public abstract class MExtractField extends TScalarBase
{
    private static int MAX_YEAR = 9999;

    public static final TScalar INSTANCES[] = new TScalar[]
    {
        new MExtractField("YEAR", MDateAndTime.DATE, Decoder.DATE)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                int ret = (int) ymd[MDateAndTime.YEAR_INDEX];
                return ret > MAX_YEAR ? -1 : ret; // mysql caps the output to [0, 9999]
            }
        },
        new MExtractField("QUARTER", MDateAndTime.DATE, Decoder.DATE)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                if (MDateAndTime.isZeroDayMonth(ymd))
                    return 0;

                int month = (int) ymd[MDateAndTime.MONTH_INDEX];

                if (month < 4) return 1;
                else if (month < 7) return 2;
                else if (month < 10) return 3;
                else return 4;
            }
        },
        new MExtractField("MONTH", MDateAndTime.DATE, Decoder.DATE)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                return (int) ymd[MDateAndTime.MONTH_INDEX];
            }
        },
        new MExtractField("DAYOFWEEK", MDateAndTime.DATE, Decoder.DATE)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                return MDateAndTime.isZeroDayMonth(ymd)
                           ? -1
                           // mysql:  (1 = Sunday, 2 = Monday, …, 7 = Saturday
                           // joda    (7 = Sunday, 1 = mon, l...., 6 = Saturday
                           : MDateAndTime.toJodaDateTime(ymd, context.getCurrentTimezone()).getDayOfWeek()
                             % 7 + 1;

            }
        },
        new MExtractField("WEEKDAY", MDateAndTime.DATE, Decoder.DATE)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                return MDateAndTime.isZeroDayMonth(ymd)
                            ? -1
                            //mysql: (0 = Monday, 1 = Tuesday, … 6 = Sunday).
                            //joda:  mon = 1, ..., sat = 6, sun = 7
                           : MDateAndTime.toJodaDateTime(ymd, context.getCurrentTimezone()).getDayOfWeek() - 1;
            }  
        },
        new MExtractField("LAST_DAY", MDateAndTime.DATE, Decoder.DATE)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                if (MDateAndTime.isZeroDayMonth(ymd))
                    return -1;
               
                ymd[2] = MDateAndTime.getLastDay(ymd);
                return MDateAndTime.encodeDate(ymd);
            }

            @Override
            public TOverloadResult resultType() {
                return TOverloadResult.fixed(MDateAndTime.DATE);
            }
        },
        new MExtractField("DAYOFYEAR", MDateAndTime.DATE, Decoder.DATE)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                return MDateAndTime.isZeroDayMonth(ymd)
                            ? -1
                            : MDateAndTime.toJodaDateTime(ymd, context.getCurrentTimezone()).getDayOfYear();
            }
        },
        new MExtractField("DAY", MDateAndTime.DATE, Decoder.DATE) // day of month
        {  
            @Override
            public String[] registeredNames()
            {
                return new String[]{"DAYOFMONTH", "DAY"};
            }

            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                return (int) ymd[MDateAndTime.DAY_INDEX];
            }
        },
        new MExtractField("HOUR", MDateAndTime.TIME, Decoder.TIME)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                // select hour('-10:10:10') should just return 10
                return Math.abs((int) ymd[MDateAndTime.HOUR_INDEX]);
            }
        },
        new MExtractField("MINUTE", MDateAndTime.TIME, Decoder.TIME)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                return (int) ymd[MDateAndTime.MIN_INDEX];
            }
        },
        new MExtractField("SECOND", MDateAndTime.TIME, Decoder.TIME)
        {
            @Override
            protected int getField(long[] ymd, TExecutionContext context)
            {
                return (int) ymd[MDateAndTime.SEC_INDEX];
            }
        },
        new TScalarBase() // DAYNAME
        {
            @Override
            protected void buildInputSets(TInputSetBuilder builder)
            {
                builder.covers(MDateAndTime.DATE, 0);
            }

            @Override
            protected void doEvaluate(TExecutionContext context, LazyList<? extends ValueSource> inputs, ValueTarget output)
            {
                int date = inputs.get(0).getInt32();
                long ymd[] = MDateAndTime.decodeDate(date);
                if(!MDateAndTime.isValidDate(ymd, MDateAndTime.ZeroFlag.YEAR))
                {
                    output.putNull();
                    context.warnClient(new InvalidDateFormatException("DATE", MDateAndTime.dateToString(date)));
                    return;
                }
                String dayName = MDateAndTime.toJodaDateTime(ymd, context.getCurrentTimezone()).dayOfWeek().
                                                                getAsText(context.getCurrentLocale());
                output.putString(dayName, null);
            }

            @Override
            public String displayName()
            {
                return "DAYNAME";
            }

            @Override
            public TOverloadResult resultType()
            {
                return TOverloadResult.fixed(MString.VARCHAR, 9);
            }
        },
        new TScalarBase() // MONTHNAME
        {
            @Override
            protected void buildInputSets(TInputSetBuilder builder)
            {
                builder.covers(MDateAndTime.DATE, 0);
            }

            @Override
            protected void doEvaluate(TExecutionContext context, LazyList<? extends ValueSource> inputs, ValueTarget output)
            {
                int date = inputs.get(0).getInt32();
                long ymd[] = MDateAndTime.decodeDate(date);
                if (!MDateAndTime.isValidDateTime(ymd, MDateAndTime.ZeroFlag.YEAR, MDateAndTime.ZeroFlag.DAY))
                {
                    output.putNull();
                    context.warnClient(new InvalidDateFormatException("DATE", MDateAndTime.dateToString(date)));
                    return;
                }
               
                int numericMonth = (int) MDateAndTime.decodeDate(inputs.get(0).getInt32())[MDateAndTime.MONTH_INDEX];
                String month = MDateAndTime.getMonthName(numericMonth,
                                                         context.getCurrentLocale().getLanguage(),
                                                         context);
                output.putString(month, null);
            }

            @Override
            public String displayName()
            {
                return "MONTHNAME";
            }

            @Override
            public TOverloadResult resultType()
            {
                return TOverloadResult.fixed(MString.VARCHAR, 9);
            }
        }
    };

    protected abstract int getField(long ymd[], TExecutionContext context);

    static enum Decoder
    {
        DATE
        {
            @Override
            long[] decode(long val)
            {
                long ret[] = MDateAndTime.decodeDate(val);
                if (!MDateAndTime.isValidDate_Zeros(ret))
                    return null;
                else
                    return ret;
            }
        },
        DATETIME
        {
            @Override
            long[] decode(long val)
            {
                long ret[] = MDateAndTime.decodeDateTime(val);
                if (!MDateAndTime.isValidDateTime_Zeros(ret))
                    return null;
                else
                    return ret;
            }
        },
        TIME
        {
            @Override
            long[] decode(long val)
            {
                long ret[] = MDateAndTime.decodeTime(val);
                if (!MDateAndTime.isValidHrMinSec(ret, false, false))
                    return null;
                else
                    return ret;
            }
        };
       
        abstract long[] decode(long val);
    }
    private final String name;
    private final TClass inputType;
    private final Decoder decoder;
    private MExtractField (String name, TClass inputType, Decoder decoder)
    {
        this.name = name;
        this.inputType = inputType;
        this.decoder = decoder;
    }

    @Override
    protected void buildInputSets(TInputSetBuilder builder)
    {
        builder.covers(inputType, 0);
    }

    @Override
    protected void doEvaluate(TExecutionContext context, LazyList<? extends ValueSource> inputs, ValueTarget output)
    {
        int val = inputs.get(0).getInt32();
        long ymd[] = decoder.decode(val);
        int ret;
        if (ymd == null || (ret = getField(ymd, context)) < 0)
        {
            context.warnClient(new InvalidParameterValueException("Invalid DATETIME value: " + val));
            output.putNull();
        }
        else
            output.putInt32(ret);
    }

    @Override
    public String displayName()
    {
        return name;
    }

    @Override
    public TOverloadResult resultType()
    {
        return TOverloadResult.fixed(MNumeric.INT);
    }
}
TOP

Related Classes of com.foundationdb.server.types.mcompat.mfuncs.MExtractField

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.