Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 36 additions & 18 deletions src/tools/search-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ConnectorManager } from "../connectors/manager.js";
import { createToolSuccessResponse, createToolErrorResponse } from "../utils/response-formatter.js";
import type { Connector } from "../connectors/interface.js";
import { quoteQualifiedIdentifier } from "../utils/identifier-quoter.js";
import { requestStore } from "../requests/index.js";
import { getClientIdentifier } from "../utils/client-identifier.js";

/**
* Object types that can be searched
Expand Down Expand Up @@ -454,7 +456,7 @@ async function searchIndexes(
* Create a search_database_objects tool handler
*/
export function createSearchDatabaseObjectsToolHandler(sourceId?: string) {
return async (args: any, _extra: any) => {
return async (args: any, extra: any) => {
const {
object_type,
pattern = "%",
Expand All @@ -471,6 +473,11 @@ export function createSearchDatabaseObjectsToolHandler(sourceId?: string) {
limit: number;
};

const startTime = Date.now();
const effectiveSourceId = sourceId || "default";
let success = true;
let errorMessage: string | undefined;

try {
const connector = ConnectorManager.getCurrentConnector(sourceId);

Expand All @@ -479,27 +486,24 @@ export function createSearchDatabaseObjectsToolHandler(sourceId?: string) {
// Validate table parameter
if (table) {
if (!schema) {
return createToolErrorResponse(
"The 'table' parameter requires 'schema' to be specified",
"SCHEMA_REQUIRED"
);
success = false;
errorMessage = "The 'table' parameter requires 'schema' to be specified";
return createToolErrorResponse(errorMessage, "SCHEMA_REQUIRED");
}
if (!["column", "index"].includes(object_type)) {
return createToolErrorResponse(
`The 'table' parameter only applies to object_type 'column' or 'index', not '${object_type}'`,
"INVALID_TABLE_FILTER"
);
success = false;
errorMessage = `The 'table' parameter only applies to object_type 'column' or 'index', not '${object_type}'`;
return createToolErrorResponse(errorMessage, "INVALID_TABLE_FILTER");
}
}

// Validate schema if provided
if (schema) {
const schemas = await connector.getSchemas();
if (!schemas.includes(schema)) {
return createToolErrorResponse(
`Schema '${schema}' does not exist. Available schemas: ${schemas.join(", ")}`,
"SCHEMA_NOT_FOUND"
);
success = false;
errorMessage = `Schema '${schema}' does not exist. Available schemas: ${schemas.join(", ")}`;
return createToolErrorResponse(errorMessage, "SCHEMA_NOT_FOUND");
}
}

Expand All @@ -523,10 +527,9 @@ export function createSearchDatabaseObjectsToolHandler(sourceId?: string) {
results = await searchIndexes(connector, pattern, schema, table, detail_level, limit);
break;
default:
return createToolErrorResponse(
`Unsupported object_type: ${object_type}`,
"INVALID_OBJECT_TYPE"
);
success = false;
errorMessage = `Unsupported object_type: ${object_type}`;
return createToolErrorResponse(errorMessage, "INVALID_OBJECT_TYPE");
}

return createToolSuccessResponse({
Expand All @@ -540,10 +543,25 @@ export function createSearchDatabaseObjectsToolHandler(sourceId?: string) {
truncated: results.length === limit,
});
} catch (error) {
success = false;
errorMessage = (error as Error).message;
return createToolErrorResponse(
`Error searching database objects: ${(error as Error).message}`,
`Error searching database objects: ${errorMessage}`,
"SEARCH_ERROR"
);
} finally {
// Track the request
requestStore.add({
id: crypto.randomUUID(),
timestamp: new Date().toISOString(),
sourceId: effectiveSourceId,
toolName: effectiveSourceId === "default" ? "search_objects" : `search_objects_${effectiveSourceId}`,
sql: `search_objects(object_type=${object_type}, pattern=${pattern}, schema=${schema || "all"}, table=${table || "all"}, detail_level=${detail_level})`,
durationMs: Date.now() - startTime,
client: getClientIdentifier(extra),
success,
error: errorMessage,
});
Comment on lines +552 to +564
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new request logging functionality lacks test coverage. While the repository has comprehensive test coverage for the search_objects tool (835 lines of tests), there are no tests verifying that requests are correctly logged to the requestStore with the appropriate success/failure status, error messages, duration, client identifier, and other fields. Consider adding tests similar to those in the requests integration tests to verify this new logging behavior.

Copilot uses AI. Check for mistakes.
}
};
}