Query syntax support
Supported statement types
QueryBolt optimizes read workloads. The core inputs are single SELECT or WITH … SELECT statements (including MySQL null-safe equals <=>, locking reads such as FOR UPDATE, and DESC as a DESCRIBE alias), multi-statement read-only query scripts, stored procedures for both MySQL 8 and SQL Server, and SQL Server temp-table staging scripts. SQL Server bitwise operators (&, |, ^, as in (Flags & 4) = 4) are supported. Constructs a generic parser cannot read, such as JSON_TABLE or MEMBER OF, are accepted in limited analysis mode when the statement is still confidently read-only and the parse failure is attributable to that construct. A typo that merely happens to contain those tokens is still rejected. Remote table functions such as OPENROWSET are refused.
Engine versions
QueryBolt supports MySQL 8.0 (8.0.31 or later) and 8.4, and SQL Server 2019 and 2022. Tests run on MySQL 8.4 and SQL Server 2022, but the SQL you get back is written for the version you run. On SQL Server, choose your version in the upload wizard. The default is 2019. It never uses functions SQL Server added in 2022, such as DATETRUNC and GREATEST/LEAST. Choose 2022 to allow them. The result page and PDF report say which version a result was written for.
Columnstore aggregate inputs
SQL Server columnstore candidates for grouped reporting queries include the stored columns used inside aggregate expressions, such as both Quantity and UnitPrice in SUM(Quantity * UnitPrice). Date expressions contribute their stored date columns. Suggestions still require plan use and measured qualification; a proposed columnstore is not a demonstrated improvement.
SQL Server date filters
On SQL Server, filters such as YEAR(OrderDate) = 2024, CAST(OrderDate AS DATE) = @day or DATEPART (including a year and a month together, as Entity Framework writes them), EOMONTH and CONVERT(date, …) are rewritten into a date range that can use an index only when your table definitions declare the column as date, datetime, datetime2 or smalldatetime. A datetimeoffset column is never rewritten this way. SQL Server compares the range at UTC, but YEAR and CAST read the stored local time, so rows near midnight would move between days. Without table definitions, QueryBolt cannot tell which type the column is, so it leaves these filters as they are. Supply your CREATE TABLE statements to get these rewrites.
Common table expressions
Non-recursive CTEs are fully supported on both engines. Subquery advice identifies the block that owns an ANY/ALL comparison. Filters on scalar aggregate outputs are not advised to move below the aggregate, including aggregates without GROUP BY. Recursive or cyclic CTEs are analyzed but never rewritten automatically - the report explains when a CTE was left untouched for safety. Structural advisories inspect CTE bodies, derived tables, subqueries, and set-operation branches in their own scope, and name the block containing a finding. Unused-column advice checks all consumers of a shared CTE and preserves columns that determine row multiplicity; predicate-pushdown advice respects row limits, aggregation, and window boundaries.
WITH recent_orders AS (
SELECT * FROM orders
WHERE created_at >= NOW() - INTERVAL 30 DAY
)
SELECT * FROM recent_orders;
Multi-statement query scripts
A script of top-level SELECT / WITH statements is split into per-statement optimizations and reassembled into one optimized script. Script runs are preview-only: each statement is optimized and validated, but the combined script is not benchmarked as a whole.
SQL Server temp-table staging scripts
A SQL Server reporting script that stages an intermediate result into a #temp (or ##temp) table or @table variable, indexes it, then reads from it is accepted when every write targets one of those temporary objects. QueryBolt runs the script in a throwaway benchmark database and optimizes the final read query. The staging statements are rebuilt inside each measurement session before the read is measured, because a #temp object exists only in the session that created it, so the staging cost never lands in a timing sample. Your report comes back as the whole script with its final read swapped in, ready to run. Only the final read is rewritten; the staging statements are reproduced exactly as you wrote them. A write to a durable table is still refused. Two variants are accepted but analyzed in preview mode instead of being benchmarked: a global ##temp table, because it is server-wide rather than scoped to your job, and a @table variable, because it only exists for the batch that declares it.
Stored procedures
MySQL CREATE PROCEDURE scripts (including DELIMITER directives) and SQL Server CREATE PROC / CREATE OR ALTER PROC batches separated by GO are decomposed into per-statement units. Safe top-level SELECT units are optimized independently. SELECT statements nested inside IF / ELSE are also analyzed for index opportunities (and may receive a nested rewrite that is spliced back into the procedure body). Procedural DML and SELECT … INTO receive advisory guidance instead of automatic rewrites. Procedure parameters such as p_customer_id are not treated as table columns, and already-sargable predicates like created_at < DATE_ADD(p_to_date, INTERVAL 1 DAY) are left unchanged rather than inverted onto the table column. Upload validation allows stored-program SQL that a generic parser would reject, including null-safe equals (<=>), the DEFAULT value keyword in INSERT / UPDATE, LIMIT p_limit, parenthesized or computed LIMIT values, and user variables. Dangerous commands are still blocked, including statements nested in IF / WHILE / handlers, SET @@global / SET @@session, and PREPARE of a literal DROP or GRANT.
Functions, triggers, and views
Functions can optimize safe RETURN (SELECT …) bodies in preview mode, and triggers receive advisory-only guidance for their DML. A single CREATE VIEW … AS SELECT upload optimizes the view’s SELECT body and returns the reassembled statement, preview-only - QueryBolt never executes or deploys your DDL.
Dynamic SQL
SQL built at runtime inside procedures (PREPARE, EXEC(…), sp_executesql) is never executed or rewritten automatically. Where the source text is statically knowable, the report includes extracted advisory guidance; otherwise it flags the dynamic SQL as opaque.
What isn’t optimized directly
Standalone INSERT, UPDATE, and DELETE statements are not rewritten automatically today. Durable SELECT … INTO is refused at upload; the SQL Server temp-staging path above is the exception, because a write to a #temp object cannot reach durable data. Anything that would change the truth-table semantics of your SQL (for example column = NULL bugs) is surfaced as an advisory finding instead of a silent rewrite.
Still stuck?
This page didn’t answer it — the QueryBolt team can help directly.