// Code generated by modernc.org/undup from the per-target vec_*.go files; DO NOT EDIT.

//go:build (freebsd && amd64) || (linux && amd64) || (linux && loong64) || (netbsd && amd64) || (openbsd && amd64) || (windows && (amd64 || arm64))

package vec

import (
	"unsafe"

	"modernc.org/libc"
	libsqlite3 "modernc.org/sqlite/lib"
)

func Xvec0Filter_knn(tls *libc.TLS, pCur uintptr, p uintptr, idxNum int32, idxStr uintptr, argc int32, argv uintptr) (r int32) {
	bp := tls.Alloc(208)
	defer tls.Free(208)
	var aMetadataIn, arrayRowidsIn, item2, knn_data, s, vector_column uintptr
	var entry3 TVec0MetadataInTextEntry
	var i, i1, k_idx, metadata_idx, n, query_idx, rc, rc1, rowid_in_idx, vectorColumnIdx int32
	var i2, j Tsize_t
	var k Ti64
	var _ /* dimensions at bp+16 */ Tsize_t
	var _ /* elementType at bp+24 */ _VectorElementType
	var _ /* entry at bp+104 */ uintptr
	var _ /* entry at bp+120 */ uintptr
	var _ /* entry at bp+128 */ TVec0MetadataInTextEntry
	var _ /* item at bp+48 */ uintptr
	var _ /* item at bp+64 */ TVec0MetadataIn
	var _ /* k_used at bp+160 */ Ti64
	var _ /* pzError at bp+40 */ uintptr
	var _ /* queryVector at bp+8 */ uintptr
	var _ /* queryVectorCleanup at bp+32 */ Tvector_cleanup
	var _ /* rowid at bp+56 */ Ti64
	var _ /* stmtChunks at bp+0 */ uintptr
	var _ /* topk_distances at bp+152 */ uintptr
	var _ /* topk_rowids at bp+144 */ uintptr
	var _ /* v at bp+112 */ Ti64
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = aMetadataIn, arrayRowidsIn, entry3, i, i1, i2, item2, j, k, k_idx, knn_data, metadata_idx, n, query_idx, rc, rc1, rowid_in_idx, s, vectorColumnIdx, vector_column
	vectorColumnIdx = idxNum
	vector_column = p + 608 + uintptr(vectorColumnIdx)*32
	arrayRowidsIn = libc.UintptrFromInt32(0)
	**(**uintptr)(__ccgo_up(bp)) = libc.UintptrFromInt32(0)
	**(**Tvector_cleanup)(__ccgo_up(bp + 32)) = __ccgo_fp(Xvector_cleanup_noop)
	knn_data = libsqlite3.Xsqlite3_malloc(tls, int32(40))
	if !(knn_data != 0) {
		return int32(m_SQLITE_NOMEM)
	}
	libc.Xmemset(tls, knn_data, 0, uint64(40))
	// array of `struct Vec0MetadataIn`, IF there are any `xxx in (...)` metadata constraints
	aMetadataIn = libc.UintptrFromInt32(0)
	query_idx = -int32(1)
	k_idx = -int32(1)
	rowid_in_idx = -int32(1)
	i = 0
	for {
		if !(i < argc) {
			break
		}
		if int32(**(**int8)(__ccgo_up(idxStr + uintptr(int32(1)+i*int32(4))))) == int32(_VEC0_IDXSTR_KIND_KNN_MATCH) {
			query_idx = i
		}
		if int32(**(**int8)(__ccgo_up(idxStr + uintptr(int32(1)+i*int32(4))))) == int32(_VEC0_IDXSTR_KIND_KNN_K) {
			k_idx = i
		}
		if int32(**(**int8)(__ccgo_up(idxStr + uintptr(int32(1)+i*int32(4))))) == int32(_VEC0_IDXSTR_KIND_KNN_ROWID_IN) {
			rowid_in_idx = i
		}
		goto _1
	_1:
		;
		i = i + 1
	}
	// make sure the query vector matches the vector column (type dimensions etc.)
	rc = Xvector_from_value(tls, **(**uintptr)(__ccgo_up(argv + uintptr(query_idx)*8)), bp+8, bp+16, bp+24, bp+32, bp+40)
	if rc != m_SQLITE_OK {
		Xvtab_set_error(tls, p, __ccgo_ts+10061, libc.VaList(bp+176, (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Fname_length, (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Fname, **(**uintptr)(__ccgo_up(bp + 40))))
		rc = int32(m_SQLITE_ERROR)
		goto cleanup
	}
	if **(**_VectorElementType)(__ccgo_up(bp + 24)) != (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Felement_type {
		Xvtab_set_error(tls, p, __ccgo_ts+10110, libc.VaList(bp+176, (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Fname_length, (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Fname, Xvector_subtype_name(tls, (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Felement_type), Xvector_subtype_name(tls, **(**_VectorElementType)(__ccgo_up(bp + 24)))))
		rc = int32(m_SQLITE_ERROR)
		goto cleanup
	}
	if **(**Tsize_t)(__ccgo_up(bp + 16)) != (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Fdimensions {
		Xvtab_set_error(tls, p, __ccgo_ts+10205, libc.VaList(bp+176, (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Fname_length, (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Fname, (*TVectorColumnDefinition)(unsafe.Pointer(vector_column)).Fdimensions, **(**Tsize_t)(__ccgo_up(bp + 16))))
		rc = int32(m_SQLITE_ERROR)
		goto cleanup
	}
	k = libsqlite3.Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(argv + uintptr(k_idx)*8)))
	if k < 0 {
		Xvtab_set_error(tls, p, __ccgo_ts+10304, 0)
		rc = int32(m_SQLITE_ERROR)
		goto cleanup
	}
	if k > int64(m_SQLITE_VEC_VEC0_K_MAX) {
		Xvtab_set_error(tls, p, __ccgo_ts+10363, libc.VaList(bp+176, k, int32(m_SQLITE_VEC_VEC0_K_MAX)))
		rc = int32(m_SQLITE_ERROR)
		goto cleanup
	}
	if k == 0 {
		(*Tvec0_query_knn_data)(unsafe.Pointer(knn_data)).Fk = 0
		(*Tvec0_cursor)(unsafe.Pointer(pCur)).Fknn_data = knn_data
		(*Tvec0_cursor)(unsafe.Pointer(pCur)).Fquery_plan = int32(_VEC0_QUERY_PLAN_KNN)
		rc = m_SQLITE_OK
		goto cleanup
	}
	// handle when a `rowid in (...)` operation was provided
	// Array of all the rowids that appear in any `rowid in (...)` constraint.
	// NULL if none were provided, which means a "full" scan.
	if rowid_in_idx >= 0 {
		arrayRowidsIn = libsqlite3.Xsqlite3_malloc(tls, int32(32))
		if !(arrayRowidsIn != 0) {
			rc1 = int32(m_SQLITE_NOMEM)
			goto cleanup
		}
		libc.Xmemset(tls, arrayRowidsIn, 0, uint64(32))
		rc1 = Xarray_init(tls, arrayRowidsIn, uint64(8), uint64(32))
		if rc1 != m_SQLITE_OK {
			goto cleanup
		}
		rc1 = libsqlite3.Xsqlite3_vtab_in_first(tls, **(**uintptr)(__ccgo_up(argv + uintptr(rowid_in_idx)*8)), bp+48)
		for {
			if !(rc1 == m_SQLITE_OK && **(**uintptr)(__ccgo_up(bp + 48)) != 0) {
				break
			}
			if (*Tvec0_vtab)(unsafe.Pointer(p)).FpkIsText != 0 {
				rc1 = Xvec0_rowid_from_id(tls, p, **(**uintptr)(__ccgo_up(bp + 48)), bp+56)
				if rc1 != m_SQLITE_OK {
					goto cleanup
				}
			} else {
				**(**Ti64)(__ccgo_up(bp + 56)) = libsqlite3.Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(bp + 48)))
			}
			rc1 = Xarray_append(tls, arrayRowidsIn, bp+56)
			if rc1 != m_SQLITE_OK {
				goto cleanup
			}
			goto _2
		_2:
			;
			rc1 = libsqlite3.Xsqlite3_vtab_in_next(tls, **(**uintptr)(__ccgo_up(argv + uintptr(rowid_in_idx)*8)), bp+48)
		}
		if rc1 != int32(m_SQLITE_DONE) {
			Xvtab_set_error(tls, p, __ccgo_ts+10431, 0)
			goto cleanup
		}
		libc.Xqsort(tls, (*TArray)(unsafe.Pointer(arrayRowidsIn)).Fz, (*TArray)(unsafe.Pointer(arrayRowidsIn)).Flength, (*TArray)(unsafe.Pointer(arrayRowidsIn)).Felement_size, __ccgo_fp(X_cmp))
	}
	i1 = 0
	for {
		if !(i1 < argc) {
			break
		}
		if !(int32(**(**int8)(__ccgo_up(idxStr + uintptr(int32(1)+i1*int32(4))))) == int32(_VEC0_IDXSTR_KIND_METADATA_CONSTRAINT) && int32(**(**int8)(__ccgo_up(idxStr + uintptr(int32(1)+i1*int32(4)+int32(2))))) == int32(_VEC0_METADATA_OPERATOR_IN)) {
			goto _3
		}
		metadata_idx = int32(**(**int8)(__ccgo_up(idxStr + uintptr(int32(1)+i1*int32(4)+int32(1))))) - int32('A')
		if !(aMetadataIn != 0) {
			aMetadataIn = libsqlite3.Xsqlite3_malloc(tls, int32(32))
			if !(aMetadataIn != 0) {
				rc = int32(m_SQLITE_NOMEM)
				goto cleanup
			}
			libc.Xmemset(tls, aMetadataIn, 0, uint64(32))
			rc = Xarray_init(tls, aMetadataIn, uint64(40), uint64(8))
			if rc != m_SQLITE_OK {
				goto cleanup
			}
		}
		libc.Xmemset(tls, bp+64, 0, uint64(40))
		(**(**TVec0MetadataIn)(__ccgo_up(bp + 64))).Fmetadata_idx = metadata_idx
		(**(**TVec0MetadataIn)(__ccgo_up(bp + 64))).Fargv_idx = i1
		switch (**(**TVec0MetadataColumnDefinition)(__ccgo_up(p + 1600 + uintptr(metadata_idx)*24))).Fkind {
		case int32(_VEC0_METADATA_COLUMN_KIND_INTEGER):
			rc = Xarray_init(tls, bp+64+8, uint64(8), uint64(16))
			if rc != m_SQLITE_OK {
				goto cleanup
			}
			rc = libsqlite3.Xsqlite3_vtab_in_first(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i1)*8)), bp+104)
			for {
				if !(rc == m_SQLITE_OK && **(**uintptr)(__ccgo_up(bp + 104)) != 0) {
					break
				}
				**(**Ti64)(__ccgo_up(bp + 112)) = libsqlite3.Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(bp + 104)))
				rc = Xarray_append(tls, bp+64+8, bp+112)
				if rc != m_SQLITE_OK {
					goto cleanup
				}
				goto _4
			_4:
				;
				rc = libsqlite3.Xsqlite3_vtab_in_next(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i1)*8)), bp+104)
			}
			if rc != int32(m_SQLITE_DONE) {
				Xvtab_set_error(tls, p, __ccgo_ts+10469, 0)
				goto cleanup
			}
		case int32(_VEC0_METADATA_COLUMN_KIND_TEXT):
			rc = Xarray_init(tls, bp+64+8, uint64(16), uint64(16))
			if rc != m_SQLITE_OK {
				goto cleanup
			}
			rc = libsqlite3.Xsqlite3_vtab_in_first(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i1)*8)), bp+120)
			for {
				if !(rc == m_SQLITE_OK && **(**uintptr)(__ccgo_up(bp + 120)) != 0) {
					break
				}
				s = libsqlite3.Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(bp + 120)))
				n = libsqlite3.Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(bp + 120)))
				(**(**TVec0MetadataInTextEntry)(__ccgo_up(bp + 128))).FzString = libsqlite3.Xsqlite3_mprintf(tls, __ccgo_ts+1874, libc.VaList(bp+176, n, s))
				if !((**(**TVec0MetadataInTextEntry)(__ccgo_up(bp + 128))).FzString != 0) {
					rc = int32(m_SQLITE_NOMEM)
					goto cleanup
				}
				(**(**TVec0MetadataInTextEntry)(__ccgo_up(bp + 128))).Fn = n
				rc = Xarray_append(tls, bp+64+8, bp+128)
				if rc != m_SQLITE_OK {
					goto cleanup
				}
				goto _5
			_5:
				;
				rc = libsqlite3.Xsqlite3_vtab_in_next(tls, **(**uintptr)(__ccgo_up(argv + uintptr(i1)*8)), bp+120)
			}
			if rc != int32(m_SQLITE_DONE) {
				Xvtab_set_error(tls, p, __ccgo_ts+10530, 0)
				goto cleanup
			}
		default:
			Xvtab_set_error(tls, p, __ccgo_ts+10588, 0)
			goto cleanup
		}
		rc = Xarray_append(tls, aMetadataIn, bp+64)
		if rc != m_SQLITE_OK {
			goto cleanup
		}
		goto _3
	_3:
		;
		i1 = i1 + 1
	}
	rc = Xvec0_chunks_iter(tls, p, idxStr, argc, argv, bp)
	if rc != m_SQLITE_OK {
		// IMP: V06942_23781
		Xvtab_set_error(tls, p, __ccgo_ts+10614, libc.VaList(bp+176, libsqlite3.Xsqlite3_errmsg(tls, (*Tvec0_vtab)(unsafe.Pointer(p)).Fdb)))
		goto cleanup
	}
	**(**uintptr)(__ccgo_up(bp + 144)) = libc.UintptrFromInt32(0)
	**(**uintptr)(__ccgo_up(bp + 152)) = libc.UintptrFromInt32(0)
	**(**Ti64)(__ccgo_up(bp + 160)) = 0
	rc = Xvec0Filter_knn_chunks_iter(tls, p, **(**uintptr)(__ccgo_up(bp)), vector_column, vectorColumnIdx, arrayRowidsIn, aMetadataIn, idxStr, argc, argv, **(**uintptr)(__ccgo_up(bp + 8)), k, bp+144, bp+152, bp+160)
	if rc != m_SQLITE_OK {
		goto cleanup
	}
	(*Tvec0_query_knn_data)(unsafe.Pointer(knn_data)).Fcurrent_idx = 0
	(*Tvec0_query_knn_data)(unsafe.Pointer(knn_data)).Fk = k
	(*Tvec0_query_knn_data)(unsafe.Pointer(knn_data)).Frowids = **(**uintptr)(__ccgo_up(bp + 144))
	(*Tvec0_query_knn_data)(unsafe.Pointer(knn_data)).Fdistances = **(**uintptr)(__ccgo_up(bp + 152))
	(*Tvec0_query_knn_data)(unsafe.Pointer(knn_data)).Fk_used = **(**Ti64)(__ccgo_up(bp + 160))
	(*Tvec0_cursor)(unsafe.Pointer(pCur)).Fknn_data = knn_data
	(*Tvec0_cursor)(unsafe.Pointer(pCur)).Fquery_plan = int32(_VEC0_QUERY_PLAN_KNN)
	rc = m_SQLITE_OK
	goto cleanup
cleanup:
	;
	libsqlite3.Xsqlite3_finalize(tls, **(**uintptr)(__ccgo_up(bp)))
	Xarray_cleanup(tls, arrayRowidsIn)
	libsqlite3.Xsqlite3_free(tls, arrayRowidsIn)
	(*(*func(*libc.TLS, uintptr))(unsafe.Pointer(bp + 32)))(tls, **(**uintptr)(__ccgo_up(bp + 8)))
	if aMetadataIn != 0 {
		i2 = uint64(0)
		for {
			if !(i2 < (*TArray)(unsafe.Pointer(aMetadataIn)).Flength) {
				break
			}
			item2 = (*TArray)(unsafe.Pointer(aMetadataIn)).Fz + uintptr(i2)*40
			j = uint64(0)
			for {
				if !(j < (*TVec0MetadataIn)(unsafe.Pointer(item2)).Farray.Flength) {
					break
				}
				if (**(**TVec0MetadataColumnDefinition)(__ccgo_up(p + 1600 + uintptr((*TVec0MetadataIn)(unsafe.Pointer(item2)).Fmetadata_idx)*24))).Fkind == int32(_VEC0_METADATA_COLUMN_KIND_TEXT) {
					entry3 = **(**TVec0MetadataInTextEntry)(__ccgo_up((*TVec0MetadataIn)(unsafe.Pointer(item2)).Farray.Fz + uintptr(j)*16))
					libsqlite3.Xsqlite3_free(tls, entry3.FzString)
				}
				goto _7
			_7:
				;
				j = j + 1
			}
			Xarray_cleanup(tls, item2+8)
			goto _6
		_6:
			;
			i2 = i2 + 1
		}
		Xarray_cleanup(tls, aMetadataIn)
	}
	libsqlite3.Xsqlite3_free(tls, aMetadataIn)
	if rc != m_SQLITE_OK {
		libsqlite3.Xsqlite3_free(tls, knn_data)
	}
	return rc
}
