@@ -184855,9 +184855,8 @@ import { createHash as createHash2 } from "crypto";
184855184855// src/lib/query-results-evaluator.ts
184856184856init_cli_executor();
184857184857init_logger();
184858- import { fstatSync, openSync, readFileSync as readFileSync4, writeFileSync } from "fs";
184858+ import { closeSync, fstatSync, mkdirSync as mkdirSync4 , openSync, readFileSync as readFileSync4, writeFileSync } from "fs";
184859184859import { dirname as dirname3, isAbsolute as isAbsolute3 } from "path";
184860- import { mkdirSync as mkdirSync4 } from "fs";
184861184860var BUILT_IN_EVALUATORS = {
184862184861 "json-decode": "JSON format decoder for query results",
184863184862 "csv-decode": "CSV format decoder for query results",
@@ -184868,12 +184867,18 @@ var metadataCache = /* @__PURE__ */ new Map();
184868184867async function extractQueryMetadata(queryPath) {
184869184868 try {
184870184869 const fd = openSync(queryPath, "r");
184871- const mtime = fstatSync(fd).mtimeMs;
184872- const cached2 = metadataCache.get(queryPath);
184873- if (cached2 && cached2.mtime === mtime) {
184874- return cached2.metadata;
184870+ let queryContent;
184871+ let mtime;
184872+ try {
184873+ mtime = fstatSync(fd).mtimeMs;
184874+ const cached2 = metadataCache.get(queryPath);
184875+ if (cached2 && cached2.mtime === mtime) {
184876+ return cached2.metadata;
184877+ }
184878+ queryContent = readFileSync4(fd, "utf-8");
184879+ } finally {
184880+ closeSync(fd);
184875184881 }
184876- const queryContent = readFileSync4(fd, "utf-8");
184877184882 const metadata = {};
184878184883 const kindMatch = queryContent.match(/@kind\s+([^\s]+)/);
184879184884 if (kindMatch) metadata.kind = kindMatch[1];
@@ -185134,7 +185139,7 @@ import { randomUUID as randomUUID2 } from "crypto";
185134185139// src/lib/sqlite-store.ts
185135185140var import_sql_asm = __toESM(require_sql_asm(), 1);
185136185141init_logger();
185137- import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, renameSync, writeFileSync as writeFileSync2 } from "fs";
185142+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
185138185143import { join as join8 } from "path";
185139185144var SqliteStore = class _SqliteStore {
185140185145 db = null;
@@ -185202,6 +185207,32 @@ var SqliteStore = class _SqliteStore {
185202185207 CREATE INDEX IF NOT EXISTS idx_annotations_category_entity
185203185208 ON annotations (category, entity_key);
185204185209 `);
185210+ this.exec(`
185211+ CREATE VIRTUAL TABLE IF NOT EXISTS annotations_fts
185212+ USING fts4(tokenize=unicode61, content, label, metadata);
185213+ `);
185214+ this.exec(`
185215+ CREATE TRIGGER IF NOT EXISTS annotations_ai
185216+ AFTER INSERT ON annotations BEGIN
185217+ INSERT INTO annotations_fts(rowid, content, label, metadata)
185218+ VALUES (new.id, new.content, new.label, new.metadata);
185219+ END;
185220+ `);
185221+ this.exec(`
185222+ CREATE TRIGGER IF NOT EXISTS annotations_ad
185223+ AFTER DELETE ON annotations BEGIN
185224+ DELETE FROM annotations_fts WHERE rowid = old.id;
185225+ END;
185226+ `);
185227+ this.exec(`
185228+ CREATE TRIGGER IF NOT EXISTS annotations_au
185229+ AFTER UPDATE ON annotations BEGIN
185230+ DELETE FROM annotations_fts WHERE rowid = old.id;
185231+ INSERT INTO annotations_fts(rowid, content, label, metadata)
185232+ VALUES (new.id, new.content, new.label, new.metadata);
185233+ END;
185234+ `);
185235+ this.backfillAnnotationsFts();
185205185236 this.exec(`
185206185237 CREATE TABLE IF NOT EXISTS query_result_cache (
185207185238 id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -185250,6 +185281,24 @@ var SqliteStore = class _SqliteStore {
185250185281 }
185251185282 this.dirty = true;
185252185283 }
185284+ /**
185285+ * Backfill the FTS index for any annotations rows that were inserted before
185286+ * the FTS table existed (schema migration). Compares row counts and rebuilds
185287+ * the entire FTS index when there is a mismatch.
185288+ */
185289+ backfillAnnotationsFts() {
185290+ const db = this.ensureDb();
185291+ const ftsCountResult = db.exec("SELECT COUNT(*) FROM annotations_fts");
185292+ const annCountResult = db.exec("SELECT COUNT(*) FROM annotations");
185293+ const ftsCount = ftsCountResult[0]?.values[0][0] ?? 0;
185294+ const annCount = annCountResult[0]?.values[0][0] ?? 0;
185295+ if (ftsCount < annCount) {
185296+ db.run("DELETE FROM annotations_fts");
185297+ db.run(
185298+ "INSERT INTO annotations_fts(rowid, content, label, metadata) SELECT id, content, label, metadata FROM annotations"
185299+ );
185300+ }
185301+ }
185253185302 /**
185254185303 * Get the number of rows modified by the last INSERT/UPDATE/DELETE.
185255185304 */
@@ -185274,7 +185323,15 @@ var SqliteStore = class _SqliteStore {
185274185323 const buffer = Buffer.from(data);
185275185324 const tmpPath = this.dbPath + ".tmp";
185276185325 writeFileSync2(tmpPath, buffer);
185277- renameSync(tmpPath, this.dbPath);
185326+ try {
185327+ renameSync(tmpPath, this.dbPath);
185328+ } catch {
185329+ writeFileSync2(this.dbPath, buffer);
185330+ try {
185331+ unlinkSync(tmpPath);
185332+ } catch {
185333+ }
185334+ }
185278185335 this.dirty = false;
185279185336 }
185280185337 /**
@@ -185425,8 +185482,8 @@ var SqliteStore = class _SqliteStore {
185425185482 params.$entity_key_prefix = filter.entityKeyPrefix + "%";
185426185483 }
185427185484 if (filter?.search) {
185428- conditions.push("(content LIKE $search OR metadata LIKE $search OR label LIKE $search)");
185429- params.$search = "%" + filter.search + "%" ;
185485+ conditions.push("id IN (SELECT rowid FROM annotations_fts WHERE annotations_fts MATCH $search)");
185486+ params.$search = filter.search;
185430185487 }
185431185488 let sql = "SELECT * FROM annotations";
185432185489 if (conditions.length > 0) {
@@ -192094,7 +192151,7 @@ var codeqlResolveTestsTool = {
192094192151};
192095192152
192096192153// src/tools/codeql/search-ql-code.ts
192097- import { closeSync, createReadStream as createReadStream3, fstatSync as fstatSync2, lstatSync, openSync as openSync2, readdirSync as readdirSync8, readFileSync as readFileSync12, realpathSync } from "fs";
192154+ import { closeSync as closeSync2 , createReadStream as createReadStream3, fstatSync as fstatSync2, lstatSync, openSync as openSync2, readdirSync as readdirSync8, readFileSync as readFileSync12, realpathSync } from "fs";
192098192155import { basename as basename8, extname as extname2, join as join19, resolve as resolve9 } from "path";
192099192156import { createInterface as createInterface3 } from "readline";
192100192157init_logger();
@@ -192160,7 +192217,7 @@ async function searchFile(filePath, regex, contextLines, maxCollect) {
192160192217 size = fstatSync2(fd).size;
192161192218 } catch {
192162192219 try {
192163- closeSync (fd);
192220+ closeSync2 (fd);
192164192221 } catch {
192165192222 }
192166192223 return { matches: [], totalCount: 0 };
@@ -192173,13 +192230,13 @@ async function searchFile(filePath, regex, contextLines, maxCollect) {
192173192230 content = readFileSync12(fd, "utf-8");
192174192231 } catch {
192175192232 try {
192176- closeSync (fd);
192233+ closeSync2 (fd);
192177192234 } catch {
192178192235 }
192179192236 return { matches: [], totalCount: 0 };
192180192237 }
192181192238 try {
192182- closeSync (fd);
192239+ closeSync2 (fd);
192183192240 } catch {
192184192241 }
192185192242 const lines = content.replace(/\r\n/g, "\n").split("\n");
@@ -192227,7 +192284,7 @@ async function searchFileStreaming(filePath, regex, contextLines, maxCollect, fd
192227192284 } catch {
192228192285 if (fd !== void 0) {
192229192286 try {
192230- closeSync (fd);
192287+ closeSync2 (fd);
192231192288 } catch {
192232192289 }
192233192290 }
@@ -195606,14 +195663,25 @@ function registerQueryResultsCacheRetrieveTool(server) {
195606195663 if (!subset2) {
195607195664 return { content: [{ type: "text", text: `Cached content not available for key: ${cacheKey2}` }] };
195608195665 }
195666+ let parsedResults;
195667+ try {
195668+ parsedResults = JSON.parse(subset2.content);
195669+ } catch {
195670+ return {
195671+ content: [{
195672+ type: "text",
195673+ text: subset2.content
195674+ }]
195675+ };
195676+ }
195609195677 return {
195610195678 content: [{
195611195679 type: "text",
195612195680 text: JSON.stringify({
195613195681 totalResults: subset2.totalResults,
195614195682 returnedResults: subset2.returnedResults,
195615195683 truncated: subset2.truncated,
195616- results: JSON.parse(subset2.content)
195684+ results: parsedResults
195617195685 }, null, 2)
195618195686 }]
195619195687 };
0 commit comments