diff --git a/internal/endtoend/testdata/virtual_table/sqlite/go/models.go b/internal/endtoend/testdata/virtual_table/sqlite/go/models.go index 12823070a0..f85063a5e7 100644 --- a/internal/endtoend/testdata/virtual_table/sqlite/go/models.go +++ b/internal/endtoend/testdata/virtual_table/sqlite/go/models.go @@ -9,7 +9,8 @@ import ( ) type Ft struct { - B string + Rowid int64 + B string } type Tbl struct { @@ -21,6 +22,7 @@ type Tbl struct { } type TblFt struct { - B string - C string + Rowid int64 + B string + C string } diff --git a/internal/endtoend/testdata/virtual_table/sqlite/go/query.sql.go b/internal/endtoend/testdata/virtual_table/sqlite/go/query.sql.go index 903d99641f..2a927f90ab 100644 --- a/internal/endtoend/testdata/virtual_table/sqlite/go/query.sql.go +++ b/internal/endtoend/testdata/virtual_table/sqlite/go/query.sql.go @@ -65,15 +65,20 @@ SELECT b, c FROM tbl_ft WHERE b MATCH ? ` -func (q *Queries) SelectAllColsTblFt(ctx context.Context, b string) ([]TblFt, error) { +type SelectAllColsTblFtRow struct { + B string + C string +} + +func (q *Queries) SelectAllColsTblFt(ctx context.Context, b string) ([]SelectAllColsTblFtRow, error) { rows, err := q.db.QueryContext(ctx, selectAllColsTblFt, b) if err != nil { return nil, err } defer rows.Close() - var items []TblFt + var items []SelectAllColsTblFtRow for rows.Next() { - var i TblFt + var i SelectAllColsTblFtRow if err := rows.Scan(&i.B, &i.C); err != nil { return nil, err } @@ -89,14 +94,15 @@ func (q *Queries) SelectAllColsTblFt(ctx context.Context, b string) ([]TblFt, er } const selectBm25Func = `-- name: SelectBm25Func :many -SELECT b, c, bm25(tbl_ft, 2.0) FROM tbl_ft +SELECT rowid, b, c, bm25(tbl_ft, 2.0) FROM tbl_ft WHERE b MATCH ? ORDER BY bm25(tbl_ft) ` type SelectBm25FuncRow struct { - B string - C string - Bm25 float64 + Rowid int64 + B string + C string + Bm25 float64 } func (q *Queries) SelectBm25Func(ctx context.Context, b string) ([]SelectBm25FuncRow, error) { @@ -108,7 +114,12 @@ func (q *Queries) SelectBm25Func(ctx context.Context, b string) ([]SelectBm25Fun var items []SelectBm25FuncRow for rows.Next() { var i SelectBm25FuncRow - if err := rows.Scan(&i.B, &i.C, &i.Bm25); err != nil { + if err := rows.Scan( + &i.Rowid, + &i.B, + &i.C, + &i.Bm25, + ); err != nil { return nil, err } items = append(items, i) @@ -206,6 +217,18 @@ func (q *Queries) SelectOneColTblFt(ctx context.Context, b string) ([]string, er return items, nil } +const selectRowID = `-- name: SelectRowID :one +SELECT rowid FROM ft +LIMIT 1 +` + +func (q *Queries) SelectRowID(ctx context.Context) (int64, error) { + row := q.db.QueryRowContext(ctx, selectRowID) + var rowid int64 + err := row.Scan(&rowid) + return rowid, err +} + const selectSnippetFunc = `-- name: SelectSnippetFunc :many SELECT snippet(tbl_ft, 0, '', '', 'aa', ?) FROM tbl_ft ` diff --git a/internal/endtoend/testdata/virtual_table/sqlite/query.sql b/internal/endtoend/testdata/virtual_table/sqlite/query.sql index ad8eeeae40..7fea42ae0a 100644 --- a/internal/endtoend/testdata/virtual_table/sqlite/query.sql +++ b/internal/endtoend/testdata/virtual_table/sqlite/query.sql @@ -1,3 +1,7 @@ +-- name: SelectRowID :one +SELECT rowid FROM ft +LIMIT 1; + -- name: SelectAllColsFt :many SELECT b FROM ft WHERE b MATCH ?; diff --git a/internal/engine/sqlite/convert.go b/internal/engine/sqlite/convert.go index 29c06fb285..64d0ea4c32 100644 --- a/internal/engine/sqlite/convert.go +++ b/internal/engine/sqlite/convert.go @@ -146,6 +146,13 @@ func (c *cc) convertCreate_virtual_table_fts5(n *parser.Create_virtual_table_stm IfNotExists: n.EXISTS_() != nil, } + // All FTS5 virtual tables implicitly contain a 'rowid' column. + stmt.Cols = append(stmt.Cols, &ast.ColumnDef{ + Colname: "rowid", + IsNotNull: true, + TypeName: &ast.TypeName{Name: "integer"}, + }) + for _, arg := range n.AllModule_argument() { var columnName string