github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/function/builtin/binary/todate.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package binary
    16  
    17  import (
    18  	"context"
    19  	"time"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    22  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    26  )
    27  
    28  // var usage = "to_date usage: "
    29  var usage = ""
    30  
    31  func ToDate(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    32  	if !vectors[1].IsScalar() {
    33  		return nil, moerr.NewInvalidArg(proc.Ctx, "the second parameter of function to_date", "not constant")
    34  	}
    35  	inputBytes0 := vector.MustStrCols(vectors[0])
    36  	inputBytes1 := vector.MustStrCols(vectors[1])
    37  	resultType := types.Type{Oid: types.T_varchar, Size: 24, Width: types.MaxVarcharLen}
    38  	if vectors[0].IsScalar() && vectors[1].IsScalar() {
    39  		results := make([]string, 1)
    40  		format := inputBytes1[0]
    41  		inputNsp := vectors[0].Nsp
    42  		result, resultNsp, err := ToDateInputBytes(proc.Ctx, inputBytes0, format, inputNsp, results)
    43  		if err != nil {
    44  			return nil, err
    45  		}
    46  		resultVector := vector.NewConstString(resultType, 1, result[0], proc.Mp())
    47  		nulls.Set(resultVector.Nsp, resultNsp)
    48  		return resultVector, nil
    49  	} else {
    50  		results := make([]string, len(inputBytes0))
    51  		format := inputBytes1[0]
    52  		inputNsp := vectors[0].Nsp
    53  		results, resultNsp, err := ToDateInputBytes(proc.Ctx, inputBytes0, format, inputNsp, results)
    54  		if err != nil {
    55  			return nil, err
    56  		}
    57  		resultVector := vector.NewWithStrings(resultType, results, resultNsp, proc.Mp())
    58  		return resultVector, nil
    59  	}
    60  }
    61  
    62  var otherFormats = map[string]string{
    63  	"MMDDYYYY":        "01022006",
    64  	"DDMMYYYY":        "02012006",
    65  	"MM-DD-YYYY":      "01-02-2006",
    66  	"DD-MM-YYYY":      "02-01-2006",
    67  	"YYYY-MM-DD":      "2006-01-02",
    68  	"YYYYMMDD":        "20060102",
    69  	"YYYYMMDD HHMMSS": "20060102 15:04:05",
    70  }
    71  
    72  func ToDateInputBytes(ctx context.Context, inputs []string, format string, inputNsp *nulls.Nulls, result []string) ([]string, *nulls.Nulls, error) {
    73  	resultNsp := new(nulls.Nulls)
    74  	for i := range inputs {
    75  		if nulls.Contains(inputNsp, uint64(i)) {
    76  			nulls.Add(resultNsp, uint64(i))
    77  			continue
    78  		}
    79  		if val, ok := otherFormats[format]; ok {
    80  			t, err := time.Parse(val, inputs[i])
    81  			if err != nil {
    82  				return nil, nil, moerr.NewInvalidArg(ctx, "date format", format)
    83  			}
    84  			result[i] = t.Format("2006-01-02") // this is our output format
    85  		} else {
    86  			//  XXX the only diff from if branch is error message.  Is this really correct?
    87  			t, err := time.Parse(val, inputs[i])
    88  			if err != nil {
    89  				return nil, nil, moerr.NewInvalidArg(ctx, "date format", format)
    90  			}
    91  			result[i] = t.Format("2006-01-02") // this is our output format
    92  		}
    93  	}
    94  	return result, resultNsp, nil
    95  }