diff --git a/pkg/sql/colexec/colexecproj/proj_const_left_ops.eg.go b/pkg/sql/colexec/colexecproj/proj_const_left_ops.eg.go index d52d4378c2f4..2cb3f65decec 100644 --- a/pkg/sql/colexec/colexecproj/proj_const_left_ops.eg.go +++ b/pkg/sql/colexec/colexecproj/proj_const_left_ops.eg.go @@ -17143,6 +17143,234 @@ func (p projDivFloat64ConstFloat64Op) Init() { p.Input.Init() } +type projDivIntervalConstInt16Op struct { + projConstOpBase + constArg duration.Duration +} + +func (p projDivIntervalConstInt16Op) Next(ctx context.Context) coldata.Batch { + // In order to inline the templated code of overloads, we need to have a + // `_overloadHelper` local variable of type `execgen.OverloadHelper`. + _overloadHelper := p.overloadHelper + // However, the scratch is not used in all of the projection operators, so + // we add this to go around "unused" error. + _ = _overloadHelper + batch := p.Input.Next(ctx) + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + vec := batch.ColVec(p.colIdx) + var col coldata.Int16s + col = vec.Int16() + projVec := batch.ColVec(p.outputIdx) + p.allocator.PerformOperation([]coldata.Vec{projVec}, func() { + // Capture col to force bounds check to work. See + // https://github.com/golang/go/issues/39756 + col := col + if projVec.MaybeHasNulls() { + // We need to make sure that there are no left over null values in the + // output vector. + projVec.Nulls().UnsetNulls() + } + projCol := projVec.Interval() + // Some operators can result in NULL with non-NULL inputs, like the JSON + // fetch value operator, ->. Therefore, _outNulls is defined to allow + // updating the output Nulls from within _ASSIGN functions when the result + // of a projection is Null. + _outNulls := projVec.Nulls() + if vec.Nulls().MaybeHasNulls() { + colNulls := vec.Nulls() + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + if !colNulls.NullAt(i) { + // We only want to perform the projection operation if the value is not null. + arg := col.Get(i) + + if arg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = p.constArg.Div(int64(arg)) + } + } + } else { + _ = projCol.Get(n - 1) + _ = col.Get(n - 1) + for i := 0; i < n; i++ { + if !colNulls.NullAt(i) { + // We only want to perform the projection operation if the value is not null. + //gcassert:bce + arg := col.Get(i) + + if arg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = p.constArg.Div(int64(arg)) + } + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + projVec.SetNulls(_outNulls.Or(colNulls)) + } else { + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + arg := col.Get(i) + + if arg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = p.constArg.Div(int64(arg)) + } + } else { + _ = projCol.Get(n - 1) + _ = col.Get(n - 1) + for i := 0; i < n; i++ { + //gcassert:bce + arg := col.Get(i) + + if arg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = p.constArg.Div(int64(arg)) + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + } + // Although we didn't change the length of the batch, it is necessary to set + // the length anyway (this helps maintaining the invariant of flat bytes). + batch.SetLength(n) + }) + return batch +} + +func (p projDivIntervalConstInt16Op) Init() { + p.Input.Init() +} + +type projDivIntervalConstInt32Op struct { + projConstOpBase + constArg duration.Duration +} + +func (p projDivIntervalConstInt32Op) Next(ctx context.Context) coldata.Batch { + // In order to inline the templated code of overloads, we need to have a + // `_overloadHelper` local variable of type `execgen.OverloadHelper`. + _overloadHelper := p.overloadHelper + // However, the scratch is not used in all of the projection operators, so + // we add this to go around "unused" error. + _ = _overloadHelper + batch := p.Input.Next(ctx) + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + vec := batch.ColVec(p.colIdx) + var col coldata.Int32s + col = vec.Int32() + projVec := batch.ColVec(p.outputIdx) + p.allocator.PerformOperation([]coldata.Vec{projVec}, func() { + // Capture col to force bounds check to work. See + // https://github.com/golang/go/issues/39756 + col := col + if projVec.MaybeHasNulls() { + // We need to make sure that there are no left over null values in the + // output vector. + projVec.Nulls().UnsetNulls() + } + projCol := projVec.Interval() + // Some operators can result in NULL with non-NULL inputs, like the JSON + // fetch value operator, ->. Therefore, _outNulls is defined to allow + // updating the output Nulls from within _ASSIGN functions when the result + // of a projection is Null. + _outNulls := projVec.Nulls() + if vec.Nulls().MaybeHasNulls() { + colNulls := vec.Nulls() + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + if !colNulls.NullAt(i) { + // We only want to perform the projection operation if the value is not null. + arg := col.Get(i) + + if arg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = p.constArg.Div(int64(arg)) + } + } + } else { + _ = projCol.Get(n - 1) + _ = col.Get(n - 1) + for i := 0; i < n; i++ { + if !colNulls.NullAt(i) { + // We only want to perform the projection operation if the value is not null. + //gcassert:bce + arg := col.Get(i) + + if arg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = p.constArg.Div(int64(arg)) + } + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + projVec.SetNulls(_outNulls.Or(colNulls)) + } else { + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + arg := col.Get(i) + + if arg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = p.constArg.Div(int64(arg)) + } + } else { + _ = projCol.Get(n - 1) + _ = col.Get(n - 1) + for i := 0; i < n; i++ { + //gcassert:bce + arg := col.Get(i) + + if arg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = p.constArg.Div(int64(arg)) + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + } + // Although we didn't change the length of the batch, it is necessary to set + // the length anyway (this helps maintaining the invariant of flat bytes). + batch.SetLength(n) + }) + return batch +} + +func (p projDivIntervalConstInt32Op) Init() { + p.Input.Init() +} + type projDivIntervalConstInt64Op struct { projConstOpBase constArg duration.Duration @@ -29918,6 +30146,16 @@ func GetProjectionLConstOperator( switch typeconv.TypeFamilyToCanonicalTypeFamily(rightType.Family()) { case types.IntFamily: switch rightType.Width() { + case 16: + return &projDivIntervalConstInt16Op{ + projConstOpBase: projConstOpBase, + constArg: c.(duration.Duration), + }, nil + case 32: + return &projDivIntervalConstInt32Op{ + projConstOpBase: projConstOpBase, + constArg: c.(duration.Duration), + }, nil case -1: default: return &projDivIntervalConstInt64Op{ diff --git a/pkg/sql/colexec/colexecproj/proj_const_right_ops.eg.go b/pkg/sql/colexec/colexecproj/proj_const_right_ops.eg.go index 7b0f6025702b..fd078519a914 100644 --- a/pkg/sql/colexec/colexecproj/proj_const_right_ops.eg.go +++ b/pkg/sql/colexec/colexecproj/proj_const_right_ops.eg.go @@ -17145,6 +17145,234 @@ func (p projDivFloat64Float64ConstOp) Init() { p.Input.Init() } +type projDivIntervalInt16ConstOp struct { + projConstOpBase + constArg int16 +} + +func (p projDivIntervalInt16ConstOp) Next(ctx context.Context) coldata.Batch { + // In order to inline the templated code of overloads, we need to have a + // `_overloadHelper` local variable of type `execgen.OverloadHelper`. + _overloadHelper := p.overloadHelper + // However, the scratch is not used in all of the projection operators, so + // we add this to go around "unused" error. + _ = _overloadHelper + batch := p.Input.Next(ctx) + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + vec := batch.ColVec(p.colIdx) + var col coldata.Durations + col = vec.Interval() + projVec := batch.ColVec(p.outputIdx) + p.allocator.PerformOperation([]coldata.Vec{projVec}, func() { + // Capture col to force bounds check to work. See + // https://github.com/golang/go/issues/39756 + col := col + if projVec.MaybeHasNulls() { + // We need to make sure that there are no left over null values in the + // output vector. + projVec.Nulls().UnsetNulls() + } + projCol := projVec.Interval() + // Some operators can result in NULL with non-NULL inputs, like the JSON + // fetch value operator, ->. Therefore, _outNulls is defined to allow + // updating the output Nulls from within _ASSIGN functions when the result + // of a projection is Null. + _outNulls := projVec.Nulls() + if vec.Nulls().MaybeHasNulls() { + colNulls := vec.Nulls() + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + if !colNulls.NullAt(i) { + // We only want to perform the projection operation if the value is not null. + arg := col.Get(i) + + if p.constArg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg.Div(int64(p.constArg)) + } + } + } else { + _ = projCol.Get(n - 1) + _ = col.Get(n - 1) + for i := 0; i < n; i++ { + if !colNulls.NullAt(i) { + // We only want to perform the projection operation if the value is not null. + //gcassert:bce + arg := col.Get(i) + + if p.constArg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg.Div(int64(p.constArg)) + } + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + projVec.SetNulls(_outNulls.Or(colNulls)) + } else { + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + arg := col.Get(i) + + if p.constArg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg.Div(int64(p.constArg)) + } + } else { + _ = projCol.Get(n - 1) + _ = col.Get(n - 1) + for i := 0; i < n; i++ { + //gcassert:bce + arg := col.Get(i) + + if p.constArg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg.Div(int64(p.constArg)) + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + } + // Although we didn't change the length of the batch, it is necessary to set + // the length anyway (this helps maintaining the invariant of flat bytes). + batch.SetLength(n) + }) + return batch +} + +func (p projDivIntervalInt16ConstOp) Init() { + p.Input.Init() +} + +type projDivIntervalInt32ConstOp struct { + projConstOpBase + constArg int32 +} + +func (p projDivIntervalInt32ConstOp) Next(ctx context.Context) coldata.Batch { + // In order to inline the templated code of overloads, we need to have a + // `_overloadHelper` local variable of type `execgen.OverloadHelper`. + _overloadHelper := p.overloadHelper + // However, the scratch is not used in all of the projection operators, so + // we add this to go around "unused" error. + _ = _overloadHelper + batch := p.Input.Next(ctx) + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + vec := batch.ColVec(p.colIdx) + var col coldata.Durations + col = vec.Interval() + projVec := batch.ColVec(p.outputIdx) + p.allocator.PerformOperation([]coldata.Vec{projVec}, func() { + // Capture col to force bounds check to work. See + // https://github.com/golang/go/issues/39756 + col := col + if projVec.MaybeHasNulls() { + // We need to make sure that there are no left over null values in the + // output vector. + projVec.Nulls().UnsetNulls() + } + projCol := projVec.Interval() + // Some operators can result in NULL with non-NULL inputs, like the JSON + // fetch value operator, ->. Therefore, _outNulls is defined to allow + // updating the output Nulls from within _ASSIGN functions when the result + // of a projection is Null. + _outNulls := projVec.Nulls() + if vec.Nulls().MaybeHasNulls() { + colNulls := vec.Nulls() + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + if !colNulls.NullAt(i) { + // We only want to perform the projection operation if the value is not null. + arg := col.Get(i) + + if p.constArg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg.Div(int64(p.constArg)) + } + } + } else { + _ = projCol.Get(n - 1) + _ = col.Get(n - 1) + for i := 0; i < n; i++ { + if !colNulls.NullAt(i) { + // We only want to perform the projection operation if the value is not null. + //gcassert:bce + arg := col.Get(i) + + if p.constArg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg.Div(int64(p.constArg)) + } + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + projVec.SetNulls(_outNulls.Or(colNulls)) + } else { + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + arg := col.Get(i) + + if p.constArg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg.Div(int64(p.constArg)) + } + } else { + _ = projCol.Get(n - 1) + _ = col.Get(n - 1) + for i := 0; i < n; i++ { + //gcassert:bce + arg := col.Get(i) + + if p.constArg == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg.Div(int64(p.constArg)) + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + } + // Although we didn't change the length of the batch, it is necessary to set + // the length anyway (this helps maintaining the invariant of flat bytes). + batch.SetLength(n) + }) + return batch +} + +func (p projDivIntervalInt32ConstOp) Init() { + p.Input.Init() +} + type projDivIntervalInt64ConstOp struct { projConstOpBase constArg int64 @@ -59098,6 +59326,16 @@ func GetProjectionRConstOperator( switch typeconv.TypeFamilyToCanonicalTypeFamily(rightType.Family()) { case types.IntFamily: switch rightType.Width() { + case 16: + return &projDivIntervalInt16ConstOp{ + projConstOpBase: projConstOpBase, + constArg: c.(int16), + }, nil + case 32: + return &projDivIntervalInt32ConstOp{ + projConstOpBase: projConstOpBase, + constArg: c.(int32), + }, nil case -1: default: return &projDivIntervalInt64ConstOp{ diff --git a/pkg/sql/colexec/colexecproj/proj_non_const_ops.eg.go b/pkg/sql/colexec/colexecproj/proj_non_const_ops.eg.go index 40b05a1fc8fd..a49dd18eeaab 100644 --- a/pkg/sql/colexec/colexecproj/proj_non_const_ops.eg.go +++ b/pkg/sql/colexec/colexecproj/proj_non_const_ops.eg.go @@ -18196,6 +18196,250 @@ func (p projDivFloat64Float64Op) Init() { p.Input.Init() } +type projDivIntervalInt16Op struct { + projOpBase +} + +func (p projDivIntervalInt16Op) Next(ctx context.Context) coldata.Batch { + // In order to inline the templated code of overloads, we need to have a + // `_overloadHelper` local variable of type `execgen.OverloadHelper`. + _overloadHelper := p.overloadHelper + // However, the scratch is not used in all of the projection operators, so + // we add this to go around "unused" error. + _ = _overloadHelper + batch := p.Input.Next(ctx) + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + projVec := batch.ColVec(p.outputIdx) + p.allocator.PerformOperation([]coldata.Vec{projVec}, func() { + if projVec.MaybeHasNulls() { + // We need to make sure that there are no left over null values in the + // output vector. + projVec.Nulls().UnsetNulls() + } + projCol := projVec.Interval() + vec1 := batch.ColVec(p.col1Idx) + vec2 := batch.ColVec(p.col2Idx) + col1 := vec1.Interval() + col2 := vec2.Int16() + // Some operators can result in NULL with non-NULL inputs, like the JSON + // fetch value operator, ->. Therefore, _outNulls is defined to allow + // updating the output Nulls from within _ASSIGN functions when the result + // of a projection is Null. + _outNulls := projVec.Nulls() + if vec1.Nulls().MaybeHasNulls() || vec2.Nulls().MaybeHasNulls() { + col1Nulls := vec1.Nulls() + col2Nulls := vec2.Nulls() + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + if !col1Nulls.NullAt(i) && !col2Nulls.NullAt(i) { + // We only want to perform the projection operation if both values are not + // null. + arg1 := col1.Get(i) + arg2 := col2.Get(i) + + if arg2 == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg1.Div(int64(arg2)) + } + } + } else { + _ = projCol.Get(n - 1) + _ = col1.Get(n - 1) + _ = col2.Get(n - 1) + for i := 0; i < n; i++ { + if !col1Nulls.NullAt(i) && !col2Nulls.NullAt(i) { + // We only want to perform the projection operation if both values are not + // null. + //gcassert:bce + arg1 := col1.Get(i) + //gcassert:bce + arg2 := col2.Get(i) + + if arg2 == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg1.Div(int64(arg2)) + } + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + projVec.SetNulls(_outNulls.Or(col1Nulls).Or(col2Nulls)) + } else { + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + arg1 := col1.Get(i) + arg2 := col2.Get(i) + + if arg2 == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg1.Div(int64(arg2)) + } + } else { + _ = projCol.Get(n - 1) + _ = col1.Get(n - 1) + _ = col2.Get(n - 1) + for i := 0; i < n; i++ { + //gcassert:bce + arg1 := col1.Get(i) + //gcassert:bce + arg2 := col2.Get(i) + + if arg2 == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg1.Div(int64(arg2)) + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + } + // Although we didn't change the length of the batch, it is necessary to set + // the length anyway (this helps maintaining the invariant of flat bytes). + batch.SetLength(n) + }) + return batch +} + +func (p projDivIntervalInt16Op) Init() { + p.Input.Init() +} + +type projDivIntervalInt32Op struct { + projOpBase +} + +func (p projDivIntervalInt32Op) Next(ctx context.Context) coldata.Batch { + // In order to inline the templated code of overloads, we need to have a + // `_overloadHelper` local variable of type `execgen.OverloadHelper`. + _overloadHelper := p.overloadHelper + // However, the scratch is not used in all of the projection operators, so + // we add this to go around "unused" error. + _ = _overloadHelper + batch := p.Input.Next(ctx) + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + projVec := batch.ColVec(p.outputIdx) + p.allocator.PerformOperation([]coldata.Vec{projVec}, func() { + if projVec.MaybeHasNulls() { + // We need to make sure that there are no left over null values in the + // output vector. + projVec.Nulls().UnsetNulls() + } + projCol := projVec.Interval() + vec1 := batch.ColVec(p.col1Idx) + vec2 := batch.ColVec(p.col2Idx) + col1 := vec1.Interval() + col2 := vec2.Int32() + // Some operators can result in NULL with non-NULL inputs, like the JSON + // fetch value operator, ->. Therefore, _outNulls is defined to allow + // updating the output Nulls from within _ASSIGN functions when the result + // of a projection is Null. + _outNulls := projVec.Nulls() + if vec1.Nulls().MaybeHasNulls() || vec2.Nulls().MaybeHasNulls() { + col1Nulls := vec1.Nulls() + col2Nulls := vec2.Nulls() + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + if !col1Nulls.NullAt(i) && !col2Nulls.NullAt(i) { + // We only want to perform the projection operation if both values are not + // null. + arg1 := col1.Get(i) + arg2 := col2.Get(i) + + if arg2 == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg1.Div(int64(arg2)) + } + } + } else { + _ = projCol.Get(n - 1) + _ = col1.Get(n - 1) + _ = col2.Get(n - 1) + for i := 0; i < n; i++ { + if !col1Nulls.NullAt(i) && !col2Nulls.NullAt(i) { + // We only want to perform the projection operation if both values are not + // null. + //gcassert:bce + arg1 := col1.Get(i) + //gcassert:bce + arg2 := col2.Get(i) + + if arg2 == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg1.Div(int64(arg2)) + } + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + projVec.SetNulls(_outNulls.Or(col1Nulls).Or(col2Nulls)) + } else { + if sel := batch.Selection(); sel != nil { + sel = sel[:n] + for _, i := range sel { + arg1 := col1.Get(i) + arg2 := col2.Get(i) + + if arg2 == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg1.Div(int64(arg2)) + } + } else { + _ = projCol.Get(n - 1) + _ = col1.Get(n - 1) + _ = col2.Get(n - 1) + for i := 0; i < n; i++ { + //gcassert:bce + arg1 := col1.Get(i) + //gcassert:bce + arg2 := col2.Get(i) + + if arg2 == 0 { + colexecerror.ExpectedError(tree.ErrDivByZero) + } + projCol[i] = arg1.Div(int64(arg2)) + } + } + // _outNulls has been updated from within the _ASSIGN function to include + // any NULLs that resulted from the projection. + // If $hasNulls is true, union _outNulls with the set of input Nulls. + // If $hasNulls is false, then there are no input Nulls. _outNulls is + // projVec.Nulls() so there is no need to call projVec.SetNulls(). + } + // Although we didn't change the length of the batch, it is necessary to set + // the length anyway (this helps maintaining the invariant of flat bytes). + batch.SetLength(n) + }) + return batch +} + +func (p projDivIntervalInt32Op) Init() { + p.Input.Init() +} + type projDivIntervalInt64Op struct { projOpBase } @@ -61815,6 +62059,10 @@ func GetProjectionOperator( switch typeconv.TypeFamilyToCanonicalTypeFamily(rightType.Family()) { case types.IntFamily: switch rightType.Width() { + case 16: + return &projDivIntervalInt16Op{projOpBase: projOpBase}, nil + case 32: + return &projDivIntervalInt32Op{projOpBase: projOpBase}, nil case -1: default: return &projDivIntervalInt64Op{projOpBase: projOpBase}, nil diff --git a/pkg/sql/colexec/execgen/cmd/execgen/overloads_bin.go b/pkg/sql/colexec/execgen/cmd/execgen/overloads_bin.go index d36aa53f6f6f..aab6000ee238 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/overloads_bin.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/overloads_bin.go @@ -145,7 +145,9 @@ func registerBinOpOutputTypes() { binOpOutputTypes[tree.Mult][typePair{types.IntervalFamily, anyWidth, numberTypeFamily, numberTypeWidth}] = types.Interval } } - binOpOutputTypes[tree.Div][typePair{types.IntervalFamily, anyWidth, types.IntFamily, anyWidth}] = types.Interval + for _, intWidth := range supportedWidthsByCanonicalTypeFamily[types.IntFamily] { + binOpOutputTypes[tree.Div][typePair{types.IntervalFamily, anyWidth, types.IntFamily, intWidth}] = types.Interval + } binOpOutputTypes[tree.Div][typePair{types.IntervalFamily, anyWidth, types.FloatFamily, anyWidth}] = types.Interval binOpOutputTypes[tree.Plus][typePair{types.TimestampTZFamily, anyWidth, types.IntervalFamily, anyWidth}] = types.TimestampTZ binOpOutputTypes[tree.Minus][typePair{types.TimestampTZFamily, anyWidth, types.IntervalFamily, anyWidth}] = types.TimestampTZ diff --git a/pkg/sql/logictest/testdata/logic_test/vectorize_overloads b/pkg/sql/logictest/testdata/logic_test/vectorize_overloads index 95f2aee0ae2a..d7faa08c8eb4 100644 --- a/pkg/sql/logictest/testdata/logic_test/vectorize_overloads +++ b/pkg/sql/logictest/testdata/logic_test/vectorize_overloads @@ -713,3 +713,24 @@ SELECT _int, _int2, _int // _int2 FROM many_types WHERE _int2 <> 0 # Regression test for incorrectly propagating an error as internal (#57773). statement error .* value out of range SELECT ((-1.234E+401)::DECIMAL * '-53 years -10 mons -377 days -08:33:40.519057'::INTERVAL::INTERVAL)::INTERVAL FROM many_types + +# Regression test for #70738. There should be overloads for INTERVAL / INT4 and +# INTERVAL / INT2. +statement ok +CREATE TABLE t70738 ( + i INTERVAL, + i2 INT2, + i4 INT4, + i8 INT8 +); +INSERT INTO t70738 VALUES ('1 day'::INTERVAL, 1, 1, 1); + +statement ok +SELECT * FROM t70738 AS t1 +JOIN t70738 as t2 ON t1.i8 = t2.i4 +WHERE (t2.i / t1.i8) = '1 day' + +statement ok +SELECT * FROM t70738 AS t1 +JOIN t70738 as t2 ON t1.i8 = t2.i2 +WHERE (t2.i / t1.i8) = '1 day'