0
0
mirror of https://github.com/tursodatabase/libsql.git synced 2025-01-19 00:41:51 +00:00
libsql/libsql-sqlite3/src/vectorvtab.c
2024-07-15 21:08:14 +04:00

213 lines
6.3 KiB
C

/*
** 2024-04-25
**
** Copyright 2024 the libSQL authors
**
** Permission is hereby granted, free of charge, to any person obtaining a copy of
** this software and associated documentation files (the "Software"), to deal in
** the Software without restriction, including without limitation the rights to
** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
** the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
******************************************************************************
**
** libSQL vector search.
*/
#if !defined(SQLITE_OMIT_VECTOR) && !defined(SQLITE_OMIT_VIRTUALTABLE)
#include "sqlite3.h"
#include "vdbeInt.h"
#include "vectorIndexInt.h"
typedef struct vectorVtab vectorVtab;
struct vectorVtab {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection */
};
typedef struct vectorVtab_cursor vectorVtab_cursor;
struct vectorVtab_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
VectorOutRows rows;
int iRow;
};
/* Column numbers */
#define VECTOR_COLUMN_IDX 0
#define VECTOR_COLUMN_VECTOR 1
#define VECTOR_COLUMN_K 2
#define VECTOR_COLUMN_OFFSET 3
static int vectorVtabConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const *argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
vectorVtab *pVtab;
int rc;
rc = sqlite3_declare_vtab(db, "CREATE TABLE x(idx hidden, vector hidden, k hidden, id);");
if( rc!=SQLITE_OK ){
return rc;
}
pVtab = sqlite3_malloc( sizeof(*pVtab) );
if( pVtab==0 ){
return SQLITE_NOMEM;
}
memset(pVtab, 0, sizeof(*pVtab));
pVtab->db = db;
*ppVtab = (sqlite3_vtab*)pVtab;
return SQLITE_OK;
}
static int vectorVtabDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
static int vectorVtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
vectorVtab *pVTab = (vectorVtab*)p;
vectorVtab_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
*ppCursor = &pCur->base;
return SQLITE_OK;
}
static int vectorVtabClose(sqlite3_vtab_cursor *cur){
vectorVtab_cursor *pCur = (vectorVtab_cursor*)cur;
vectorVtab *pVTab = (vectorVtab *)cur->pVtab;
vectorOutRowsFree(pVTab->db, &pCur->rows);
sqlite3_free(pCur);
return SQLITE_OK;
}
static int vectorVtabNext(sqlite3_vtab_cursor *cur){
vectorVtab_cursor *pCur = (vectorVtab_cursor*)cur;
pCur->iRow++;
return SQLITE_OK;
}
static int vectorVtabEof(sqlite3_vtab_cursor *cur){
vectorVtab_cursor *pCur = (vectorVtab_cursor*)cur;
return pCur->iRow >= pCur->rows.nRows;
}
static int vectorVtabColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *context, /* First argument to sqlite3_result_...() */
int iCol /* Which column to return */
){
vectorVtab_cursor *pCur = (vectorVtab_cursor*)cur;
vectorOutRowsGet(context, &pCur->rows, pCur->iRow, iCol - VECTOR_COLUMN_OFFSET);
return SQLITE_OK;
}
static int vectorVtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
vectorVtab_cursor *pCur = (vectorVtab_cursor*)cur;
if( pCur->rows.aRowids != NULL ){
*pRowid = pCur->rows.aRowids[pCur->iRow];
}else{
*pRowid = pCur->iRow;
}
return SQLITE_OK;
}
static int vectorVtabFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
vectorVtab_cursor *pCur = (vectorVtab_cursor *)pVtabCursor;
vectorVtab *pVTab = (vectorVtab *)pVtabCursor->pVtab;
pCur->rows.aRowids = NULL;
pCur->rows.ppValues = NULL;
if( vectorIndexSearch(pVTab->db, argc, argv, &pCur->rows, &pVTab->base.zErrMsg) != 0 ){
return SQLITE_ERROR;
}
assert( pCur->rows.nRows >= 0 );
assert( pCur->rows.nCols > 0 );
pCur->iRow = 0;
return SQLITE_OK;
}
static int vectorVtabBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
const struct sqlite3_index_constraint *pConstraint;
int i;
pIdxInfo->estimatedCost = (double)1;
pIdxInfo->estimatedRows = 100;
pIdxInfo->idxNum = 1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->usable==0 ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
switch( pConstraint->iColumn ){
case VECTOR_COLUMN_IDX:
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
pIdxInfo->aConstraintUsage[i].omit = 1;
break;
case VECTOR_COLUMN_VECTOR:
pIdxInfo->aConstraintUsage[i].argvIndex = 2;
pIdxInfo->aConstraintUsage[i].omit = 1;
break;
case VECTOR_COLUMN_K:
pIdxInfo->aConstraintUsage[i].argvIndex = 3;
pIdxInfo->aConstraintUsage[i].omit = 1;
break;
}
}
return SQLITE_OK;
}
static sqlite3_module vectorModule = {
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ vectorVtabConnect,
/* xBestIndex */ vectorVtabBestIndex,
/* xDisconnect */ vectorVtabDisconnect,
/* xDestroy */ 0,
/* xOpen */ vectorVtabOpen,
/* xClose */ vectorVtabClose,
/* xFilter */ vectorVtabFilter,
/* xNext */ vectorVtabNext,
/* xEof */ vectorVtabEof,
/* xColumn */ vectorVtabColumn,
/* xRowid */ vectorVtabRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0,
/* xIntegrity */ 0
};
int vectorVtabInit(sqlite3 *db){
return sqlite3_create_module(db, VECTOR_INDEX_VTAB_NAME, &vectorModule, 0);
}
#endif /* !defined(SQLITE_OMIT_VECTOR) && !defined(SQLITE_OMIT_VIRTUALTABLE) */