github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/function/operator/coalesce.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 operator
    16  
    17  import (
    18  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    19  	"github.com/matrixorigin/matrixone/pkg/container/types"
    20  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    21  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    22  )
    23  
    24  var (
    25  	CoalesceUint8 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    26  		return coalesceGeneral[uint8](vs, proc, types.Type{Oid: types.T_uint8})
    27  	}
    28  
    29  	CoalesceUint16 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    30  		return coalesceGeneral[uint16](vs, proc, types.Type{Oid: types.T_uint16})
    31  	}
    32  
    33  	CoalesceUint32 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    34  		return coalesceGeneral[uint32](vs, proc, types.Type{Oid: types.T_uint32})
    35  	}
    36  
    37  	CoalesceUint64 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    38  		return coalesceGeneral[uint64](vs, proc, types.Type{Oid: types.T_uint64})
    39  	}
    40  
    41  	CoalesceInt8 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    42  		return coalesceGeneral[int8](vs, proc, types.Type{Oid: types.T_int8})
    43  	}
    44  
    45  	CoalesceInt16 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    46  		return coalesceGeneral[int16](vs, proc, types.Type{Oid: types.T_int16})
    47  	}
    48  
    49  	CoalesceInt32 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    50  		return coalesceGeneral[int32](vs, proc, types.Type{Oid: types.T_int32})
    51  	}
    52  
    53  	CoalesceInt64 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    54  		return coalesceGeneral[int64](vs, proc, types.Type{Oid: types.T_int64})
    55  	}
    56  
    57  	CoalesceFloat32 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    58  		return coalesceGeneral[float32](vs, proc, types.Type{Oid: types.T_float32})
    59  	}
    60  
    61  	CoalesceFloat64 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    62  		return coalesceGeneral[float64](vs, proc, types.Type{Oid: types.T_float64})
    63  	}
    64  
    65  	CoalesceBool = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    66  		return coalesceGeneral[bool](vs, proc, types.Type{Oid: types.T_bool})
    67  	}
    68  
    69  	CoalesceDate = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    70  		return coalesceGeneral[types.Date](vs, proc, types.Type{Oid: types.T_date})
    71  	}
    72  
    73  	CoalesceTime = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    74  		return coalesceGeneral[types.Time](vs, proc, types.Type{Oid: types.T_time})
    75  	}
    76  
    77  	CoalesceDateTime = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    78  		return coalesceGeneral[types.Datetime](vs, proc, types.Type{Oid: types.T_datetime})
    79  	}
    80  
    81  	CoalesceVarchar = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    82  		return coalesceString(vs, proc, types.Type{Oid: types.T_varchar, Width: types.MaxVarcharLen})
    83  	}
    84  
    85  	CoalesceChar = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    86  		return coalesceString(vs, proc, types.Type{Oid: types.T_char})
    87  	}
    88  
    89  	CoalesceJson = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    90  		return coalesceString(vs, proc, types.Type{Oid: types.T_json.ToType().Oid})
    91  	}
    92  
    93  	CoalesceBlob = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    94  		return coalesceString(vs, proc, types.Type{Oid: types.T_blob.ToType().Oid})
    95  	}
    96  
    97  	CoalesceText = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    98  		return coalesceString(vs, proc, types.Type{Oid: types.T_text.ToType().Oid})
    99  	}
   100  
   101  	CoalesceDecimal64 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   102  		return coalesceGeneral[types.Decimal64](vs, proc, types.Type{Oid: types.T_decimal64})
   103  	}
   104  
   105  	CoalesceDecimal128 = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   106  		return coalesceGeneral[types.Decimal128](vs, proc, types.Type{Oid: types.T_decimal128})
   107  	}
   108  
   109  	CoalesceTimestamp = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   110  		return coalesceGeneral[types.Timestamp](vs, proc, types.Type{Oid: types.T_timestamp})
   111  	}
   112  
   113  	CoalesceUuid = func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   114  		return coalesceGeneral[types.Uuid](vs, proc, types.Type{Oid: types.T_uuid})
   115  	}
   116  )
   117  
   118  // CoalesceTypeCheckFn is type check function for coalesce operator
   119  func CoalesceTypeCheckFn(inputTypes []types.T, _ []types.T, ret types.T) bool {
   120  	l := len(inputTypes)
   121  	for i := 0; i < l; i++ {
   122  		if inputTypes[i] != ret && inputTypes[i] != types.T_any {
   123  			return false
   124  		}
   125  	}
   126  	return true
   127  }
   128  
   129  // coalesceGeneral is a general evaluate function for coalesce operator
   130  // when return type is uint / int / float / bool / date / datetime
   131  func coalesceGeneral[T NormalType](vs []*vector.Vector, proc *process.Process, t types.Type) (*vector.Vector, error) {
   132  	vecLen := vector.Length(vs[0])
   133  	startIdx := 0
   134  	for i := 0; i < len(vs); i++ {
   135  		input := vs[i]
   136  		if input.IsScalar() {
   137  			if !input.IsScalarNull() {
   138  				cols := vector.MustTCols[T](input)
   139  				r := proc.AllocScalarVector(t)
   140  				r.Typ.Precision = input.Typ.Precision
   141  				r.Typ.Width = input.Typ.Width
   142  				r.Typ.Scale = input.Typ.Scale
   143  				r.Col = make([]T, 1)
   144  				r.Col.([]T)[0] = cols[0]
   145  				return r, nil
   146  			}
   147  		} else {
   148  			startIdx = i
   149  			break
   150  		}
   151  	}
   152  
   153  	rs, err := proc.AllocVector(t, int64(vecLen*t.Oid.TypeLen()))
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	rs.Col = vector.DecodeFixedCol[T](rs, t.Oid.TypeLen())
   158  	rs.Col = rs.Col.([]T)[:vecLen]
   159  	rsCols := rs.Col.([]T)
   160  
   161  	rs.Nsp = nulls.NewWithSize(vecLen)
   162  	rs.Nsp.Np.AddRange(0, uint64(vecLen))
   163  
   164  	for i := startIdx; i < len(vs); i++ {
   165  		input := vs[i]
   166  		if input.Typ.Oid != types.T_any {
   167  			rs.Typ = input.Typ
   168  		}
   169  		cols := vector.MustTCols[T](input)
   170  		if input.IsScalar() {
   171  			if input.IsScalarNull() {
   172  				continue
   173  			}
   174  
   175  			for j := 0; j < vecLen; j++ {
   176  				if rs.Nsp.Contains(uint64(j)) {
   177  					rsCols[j] = cols[0]
   178  				}
   179  			}
   180  			rs.Nsp.Np = nil
   181  			return rs, nil
   182  		} else {
   183  			nullsLength := nulls.Length(input.Nsp)
   184  			if nullsLength == vecLen {
   185  				// all null do nothing
   186  				continue
   187  			} else if nullsLength == 0 {
   188  				// all not null
   189  				for j := 0; j < vecLen; j++ {
   190  					if rs.Nsp.Contains(uint64(j)) {
   191  						rsCols[j] = cols[j]
   192  					}
   193  				}
   194  				rs.Nsp.Np = nil
   195  				return rs, nil
   196  			} else {
   197  				// some nulls
   198  				for j := 0; j < vecLen; j++ {
   199  					if rs.Nsp.Contains(uint64(j)) && !input.Nsp.Contains(uint64(j)) {
   200  						rsCols[j] = cols[j]
   201  						rs.Nsp.Np.Remove(uint64(j))
   202  					}
   203  				}
   204  
   205  				if rs.Nsp.Np.IsEmpty() {
   206  					rs.Nsp.Np = nil
   207  					return rs, nil
   208  				}
   209  			}
   210  		}
   211  	}
   212  
   213  	return rs, nil
   214  }
   215  
   216  // coalesceGeneral is a general evaluate function for coalesce operator
   217  // when return type is char / varchar
   218  func coalesceString(vs []*vector.Vector, proc *process.Process, typ types.Type) (*vector.Vector, error) {
   219  	vecLen := vector.Length(vs[0])
   220  	startIdx := 0
   221  
   222  	// If leading expressions are non null scalar, return.   Otherwise startIdx
   223  	// is positioned at the first non scalar vector.
   224  	for i := 0; i < len(vs); i++ {
   225  		input := vs[i]
   226  		if input.IsScalar() {
   227  			if !input.IsScalarNull() {
   228  				cols := vector.MustStrCols(input)
   229  				return vector.NewConstString(typ, input.Length(), cols[0], proc.Mp()), nil
   230  			}
   231  		} else {
   232  			startIdx = i
   233  			break
   234  		}
   235  	}
   236  
   237  	rs := make([]string, vecLen)
   238  	nsp := nulls.NewWithSize(vecLen)
   239  	nsp.Np.AddRange(0, uint64(vecLen))
   240  
   241  	for i := startIdx; i < len(vs); i++ {
   242  		input := vs[i]
   243  		cols := vector.MustStrCols(input)
   244  		if input.IsScalar() {
   245  			if input.IsScalarNull() {
   246  				continue
   247  			}
   248  			for j := 0; j < vecLen; j++ {
   249  				if nsp.Contains(uint64(j)) {
   250  					rs[j] = cols[0]
   251  				}
   252  			}
   253  			nsp = nil
   254  			break
   255  		} else {
   256  			nullsLength := nulls.Length(input.Nsp)
   257  			if nullsLength == vecLen {
   258  				// all null do nothing
   259  				continue
   260  			} else if nullsLength == 0 {
   261  				// all not null
   262  				for j := 0; j < vecLen; j++ {
   263  					if nsp.Contains(uint64(j)) {
   264  						rs[j] = cols[j]
   265  					}
   266  				}
   267  				nsp = nil
   268  				break
   269  			} else {
   270  				// some nulls
   271  				for j := 0; j < vecLen; j++ {
   272  					if nsp.Contains(uint64(j)) && !input.Nsp.Contains(uint64(j)) {
   273  						rs[j] = cols[j]
   274  						nsp.Np.Remove(uint64(j))
   275  					}
   276  				}
   277  
   278  				// now if is empty, break
   279  				if nsp.Np.IsEmpty() {
   280  					nsp = nil
   281  					break
   282  				}
   283  			}
   284  		}
   285  	}
   286  
   287  	return vector.NewWithStrings(typ, rs, nsp, proc.Mp()), nil
   288  }