Skip to content
Open
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
52 changes: 49 additions & 3 deletions query/src/org/labkey/query/controllers/QueryMcp.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
import org.labkey.api.query.QueryForeignKey;
import org.labkey.api.query.QueryKey;
import org.labkey.api.query.QueryParseException;
import org.labkey.api.query.QueryParseWarning;
import org.labkey.api.query.QuerySchema;
import org.labkey.api.query.QueryService;
import org.labkey.api.query.SchemaKey;
import org.labkey.api.query.SimpleSchemaTreeVisitor;
import org.labkey.api.query.UserSchema;
Expand Down Expand Up @@ -78,7 +81,7 @@ String listSchemas(ToolContext toolContext)

@Tool(description = "Provide list of tables within the provided schema.")
@RequiresPermission(ReadPermission.class)
String listTables(ToolContext toolContext, @ToolParam(description = "Fully qualified schema name as it would appear in SQL e.g. Study or \"Study.Datasets\"") String schemaName)
String listTables(ToolContext toolContext, @ToolParam(description = "Fully qualified schema name as it would appear in SQL e.g. Study or \"Study\".\"Datasets\"") String schemaName)
{
var json = _listTables(getContext(toolContext), schemaName);
return json.toString();
Expand All @@ -100,7 +103,7 @@ String listColumns(
@RequiresPermission(ReadPermission.class)
String getSourceForSavedQuery(
ToolContext toolContext,
@ToolParam(description = "Fully qualified schema name as it would appear in SQL e.g. Study or \"Study.Datasets\"") String schemaName,
@ToolParam(description = "Fully qualified schema name as it would appear in SQL e.g. Study or \"Study\".\"Datasets\"") String schemaName,
@ToolParam(description = "Table or query name as it would appear in SQL e.g. MyTable, MyQuery, or \"MyTable\"") String queryName
)
{
Expand All @@ -111,6 +114,49 @@ String getSourceForSavedQuery(
throw new NotFoundException("Could not find the source for " + schemaName + "." + queryName);
}

@Tool(description = "Validate SQL syntax.")
@RequiresPermission(ReadPermission.class)
String validateSQL(
ToolContext toolContext,
@ToolParam(description = "Fully qualified schema name as it would appear in SQL e.g. Study or \"Study\".\"Datasets\"") String schemaName,
@ToolParam(description = "SQL source") String sql
)
{
var context = getContext(toolContext);

SchemaKey schemaKey = getSchemaKey(schemaName);
QuerySchema schema = DefaultSchema.get(context.getUser(), context.getContainer(), schemaKey);

try
{
TableInfo ti = QueryService.get().createTable(schema, sql, null, true);
var warnings = ti.getWarnings();
if (null != warnings)
{
var warning = warnings.stream().findFirst();
if (warning.isPresent())
throw warning.get();
}
// CONSIDER: add back code to add database validate, but this seems to have stopped working
// if (ti.getSqlDialect().isPostgreSQL())
// {
// var parameters = ti.getNamedParameters();
// if (parameters.isEmpty())
// {
// SQLFragment sqlPrepare = new SQLFragment("PREPARE validate AS SELECT * FROM ").append(ti.getFromSQL("MYVALIDATEQUERY__"));
// new SqlExecutor(ti.getSchema().getScope()).execute(sqlPrepare);
// }
// }
}
catch (Exception x)
{
// CONSIDER remove line line/character information from DB errors as they won't match the LabKey SQL
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this comment only relevant if the commented-out code above is restore?

return "That SQL caused the " + (x instanceof QueryParseWarning ? "warning" : "error") + " below:\n```" + x.getMessage() + "```";
}
return "success";
}


/* For now, list all schemas. CONSIDER support incremental querying. */
public static Map<SchemaKey, UserSchema> _listAllSchemas(DefaultSchema root)
{
Expand Down Expand Up @@ -309,7 +355,7 @@ static String normalizeIdentifier(String compoundIdentifier)
return new SqlParser().parseIdentifier(compoundIdentifier).toSQLString(true).toLowerCase();
}

/** JSON schema example provided by GEMINI, using triple tick-marks to delimit the machine-readable structured data
/* JSON schema example provided by GEMINI, using triple tick-marks to delimit the machine-readable structured data
*
* Here is the database schema in JSON format:
* ```{
Expand Down
Loading