You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: range_offset_handler_tmpl.go
    path of file: ./repos/cockroach/pkg/sql/colexec/colexecwindow
    
    the code of the file until where you have to start completion: // Copyright 2021 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

// {{/*
//go:build execgen_template
// +build execgen_template

//
// This file is the execgen template for range_offset_handler.eg.go. It's
// formatted in a special way, so it's both valid Go and a valid text/template
// input. This permits editing this file with editor support.
//
// */}}

package colexecwindow

import (
	"context"

	"github.com/cockroachdb/apd/v3"
	"github.com/cockroachdb/cockroach/pkg/col/coldata"
	"github.com/cockroachdb/cockroach/pkg/col/coldataext"
	"github.com/cockroachdb/cockroach/pkg/col/typeconv"
	"github.com/cockroachdb/cockroach/pkg/sql/colconv"
	"github.com/cockroachdb/cockroach/pkg/sql/colexec/colexecutils"
	"github.com/cockroachdb/cockroach/pkg/sql/colexecerror"
	"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
	"github.com/cockroachdb/cockroach/pkg/sql/execinfrapb"
	"github.com/cockroachdb/cockroach/pkg/sql/sem/eval"
	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
	"github.com/cockroachdb/cockroach/pkg/sql/types"
	"github.com/cockroachdb/cockroach/pkg/util/duration"
	"github.com/cockroachdb/cockroach/pkg/util/timeutil/pgdate"
	"github.com/cockroachdb/errors"
)

// Workaround for bazel auto-generated
    
func (h *_OP_STRING) getIdx(ctx context.Context, currRow, lastIdx int) (idx int) {
	// {{if eq .VecMethod "Datum"}}
	// {{/*
	//     In order to inline the templated code of the binary overloads
	//     operating on datums, we need to have a `_overloadHelper` local
	//     variable of type `colexecutils.BinaryOverloadHelper`. This is
	//     necessary when dealing with Time and TimeTZ columns since they aren't
	//     yet handled natively.
	// */}}
	_overloadHelper := h.overloadHelper
	_ctx := ctx
	// {{end}}

	if lastIdx >= h.storedCols.Length() {
		return lastIdx
	}

	var vec coldata.Vec
	var vecIdx, n int
	vec, vecIdx, _ = h.storedCols.GetVecWithTuple(ctx, h.ordColIdx, currRow)

	// When the order column is null, the offset is ignored. The start index is
	// the first null value, and the end index is the end of the null group. All
	// null rows have the same start and end indices.
	if vec.Nulls().MaybeHasNulls() && vec.Nulls().NullAt(vecIdx) {
		// Since this function is only called for the first row of each peer group,
		// this is the first null row.
		idx = currRow
		// {{if not .IsStart}}
		// We need to scan beyond the last null to retrieve the end index.
		idx++
		for {
			if idx >= h.storedCols.Length() {
				break
			}
			vec, vecIdx, n = h.storedCols.GetVecWithTuple(ctx, h.peersColIdx, idx)
			peersCol := vec.Bool()
			_, _ = peersCol[vecIdx], peersCol[n-1]
			for ; vecIdx < n; vecIdx++ {
				//gcassert:bce
				if peersCol[vecIdx] {
					return idx
				}
				idx++
			}
		}
		// {{end}}
		return idx
	}

	// The current row is not null. Retrieve the value that is equal to that at
	// the current row plus (minus if descending) 'offset' logical units.
	var (
		seekVal   _CMP_GOTYPE
		cmpResult int
	)
	col := vec.TemplateType()
	currRowVal := col.Get(vecIdx)
	_VALUE_BY_OFFSET(seekVal, currRowVal, h.offset)

	// Pick up where the last index left off, since the start and indexes of each
	// successive window frame are non-decreasing as we increment the current row.
	// (This follows from the fact that offsets are required to be constants).
	idx = lastIdx

	// {{if .IsOrdColAsc}}
	// If the ordering column is null at lastIdx, we must have just moved past the
	// end of the null rows (we already checked that the current row isn't null).
	// The index is only updated when a new peer group is encountered, and
	// non-null and null rows are never part of the same frame. So, we have to
	// iterate past any leading nulls.
	// {{/* Only do this for an ascending column because nulls order first. */}}
	vec, vecIdx, _ = h.storedCols.GetVecWithTuple(ctx, h.ordColIdx, idx)
	if vec.Nulls().MaybeHasNulls() && vec.Nulls().NullAt(vecIdx) {
		idx++
		var foundNonNull bool
		for {
			if idx >= h.storedCols.Length() {
				return idx
			}
			vec, vecIdx, n = h.storedCols.GetVecWithTuple(ctx, h.peersColIdx, idx)
			peersCol := vec.Bool()
			_, _ = peersCol[vecIdx], peersCol[n-1]
			for ; vecIdx < n; vecIdx++ {
				//gcassert:bce
				if peersCol[vecIdx] {
					// We have scanned past the null rows. We can't return yet, since we
					// may still need to continue scanning past non-null rows.
					foundNonNull = true
					break
				}
				idx++
			}
			if foundNonNull {
				break
			}
		}
	}
	// {{end}}

	// Scan to the next peer group and then compare to the value indicated by
	// the offset. If the comparison fails, scan again to the next peer group
	// and repeat.
	var peersVec coldata.Vec
	for {
		if idx >= h.storedCols.Length() {
			break
		}
		peersVec, vecIdx, n = h.storedCols.GetVecWithTuple(ctx, h.peersColIdx, idx)
		vec, _, _ = h.storedCols.GetVecWithTuple(ctx, h.ordColIdx, idx)
		peersCol := peersVec.Bool()
		col = vec.TemplateType()
		_, _ = peersCol[vecIdx], peersCol[n-1]
		for ; vecIdx < n; vecIdx++ {
			//gcassert:bce
			if peersCol[vecIdx] {
				// {{if not .IsOrdColAsc}}
				// Nulls and non-nulls are never part of the same window frame, which
				// means that this index must be the end of the current frame.
				// {{/*
				// We only have to check for nulls when the column is descending because
				// nulls order first and we only scan forward from the last index.
				// */}}
				if vec.Nulls().MaybeHasNulls() && vec.Nulls().NullAt(vecIdx) {
					return idx
				}
				// {{end}}
				cmpVal := col.Get(vecIdx)
				_ASSIGN_CMP(cmpResult, cmpVal, seekVal, col)
				// {{if .IsOrdColAsc}}
				// {{if .IsStart}}
				if cmpResult >= 0 {
					return idx
				}
				// {{else}}
				if cmpResult > 0 {
					return idx
				}
				// {{end}}
				// {{else}}
				// {{if .IsStart}}
				if cmpResult <= 0 {
					return idx
				}
				// {{else}}
				if cmpResult < 0 {
					return idx
				}
				// {{end}}
				// {{end}}
			}
			idx++
		}
	}
	return idx
}