A day in the life of a SQL query

Guilherme Menezes

Guilherme Menezes

Co-Founder and Chief Architect

At WisdomAI, we take pride in having a fast, cheap and accurate data querying and visualization generation system.

Data makes its way into our pipeline through multiple mechanisms:

  • SQL queries to warehouses and databases

  • Uploaded structured or unstructured files

  • Live MCP connections

Out of these, SQL queries are the most commonly used mechanism in WisdomAI.

A SQL is born

SQL generation specifically requires us to handle multiple requirements:

  1. Consistency - correct SQLs need to be consistently generated based on prior learned context

  2. Efficiency - SQLs need to burn the lowest amount of compute in a warehouse, and be served from the Wisdom cache whenever possible

  3. Cost - we need to use the minimal amount of tokens while generating the SQL

  4. Latency - we need to generate SQL queries as quickly as possible, especially for repeated queries

  5. Security - SQLs need to contain specific security constraints, such as Row-Level Security or Column-Level Security invariants

The WisdomAI Analytics Harness smartly makes use of generation optimization and context selection techniques to achieve these requirements.

The life of a SQL query does not end, however, at the moment it is generated. Once created, the SQL goes through a series of transformations that ensure correctness, efficiency, and security in a deterministic setup.

SQL grows into a dataframe

In WisdomAI, SQL is not just a string. It is a data structure we own.

As soon as the SQL is created, we parse its syntax tree and map it to a WisdomAI-owned dataframe data structure. This allows us to represent a SQL in a dialect-agnostic manner. It also provides us with a mechanism to apply deterministic transformations or verifications before the SQL goes out to a warehouse.

Like other dataframe libraries, the WisdomAI dataframe is defined by a sequence of lower-level operators: Join, Select, GroupBy, Filter, OrderBy, etc. It is also defined recursively, such that a WisdomAI dataframe can join against another WisdomAI dataframe, for example.

One key example of where this is useful is when applying Row-Level Security (RLS) configurations.

Example: Row-Level Security (RLS)

A table in the WisdomAI data model can be configured to apply RLS rules. These are essentially mandatory WHERE clauses that need to always be associated with the target table.

RLS rules need to be deterministically applied to the SQL. We cannot leave the WHERE clause generation to a non-deterministic LLM.

For example, let’s assume we have the following table:

CREATE TABLE account (
    id       BIGINT PRIMARY KEY,
    name     VARCHAR(255),
    region   VARCHAR(64),
    arr      NUMERIC(18, 2),
    user_id  BIGINT
)

CREATE TABLE account (
    id       BIGINT PRIMARY KEY,
    name     VARCHAR(255),
    region   VARCHAR(64),
    arr      NUMERIC(18, 2),
    user_id  BIGINT
)

CREATE TABLE account (
    id       BIGINT PRIMARY KEY,
    name     VARCHAR(255),
    region   VARCHAR(64),
    arr      NUMERIC(18, 2),
    user_id  BIGINT
)

CREATE TABLE account (
    id       BIGINT PRIMARY KEY,
    name     VARCHAR(255),
    region   VARCHAR(64),
    arr      NUMERIC(18, 2),
    user_id  BIGINT
)

Not every user is allowed to see every account. The admin configures a single RLS rule on the table:

WHERE USER_ATTRIBUTE('user_id')
WHERE USER_ATTRIBUTE('user_id')
WHERE USER_ATTRIBUTE('user_id')
WHERE USER_ATTRIBUTE('user_id')

In this case, user_id is a user-level attribute associated with the current user using WisdomAI.

That rule lives in the WisdomAI data model, written once. It is never shown to the LLM and never regenerated.

Now a user asks show me all accounts. The generated SQL is the obvious one:

SELECT * FROM
SELECT * FROM
SELECT * FROM
SELECT * FROM

This SQL is correct, but unsafe. Before it leaves Wisdom, the RLS transformation rewrites it into:

WITH account_authz AS (
	SELECT *
	FROM account
	WHERE 'id_of_the_user_querying' = account.user_id
)
SELECT *
FROM account_authz AS

WITH account_authz AS (
	SELECT *
	FROM account
	WHERE 'id_of_the_user_querying' = account.user_id
)
SELECT *
FROM account_authz AS

WITH account_authz AS (
	SELECT *
	FROM account
	WHERE 'id_of_the_user_querying' = account.user_id
)
SELECT *
FROM account_authz AS

WITH account_authz AS (
	SELECT *
	FROM account
	WHERE 'id_of_the_user_querying' = account.user_id
)
SELECT *
FROM account_authz AS

In this example, note that we expanded the user_id attribute to its actual value before sending the query for execution.

More examples

Here are a few more example transformations deterministically executed by Wisdom:

  1. Semantic layer - replace derived tables or derived columns by their definition

  2. Governance - Column-Level Security, column masking, k-anonymity

  3. Performance - derive and inject partition predicates so we don't table-scan a petabyte

The transforms are implemented in the Rust programming language to guarantee the lowest possible latency. These are applied on every single execution, including those in chats, apps, dashboards, agents and background jobs.

SQL leaves home (finally!)

Once the deterministic transforms are applied, the dataframe is re-composed into a SQL string using the correct output dialect. Then there are two possible paths:

  1. There is a cache hit (more on this in a later article - it can get complicated)

  2. The SQL goes out of our system into the external warehouse

This happens through the dataframe collect() procedure. This is when the dataframe’s data is materialized into WisdomAI. WisdomAI will store the data as Parquet files in the system’s object store, where it can be later previewed, paginated and further re-processed as part of subsequent queries or Python transformations.

Yes, SQL generation is harder than it looks

Here is why:

  1. Wisdom generates native SQL instead of using weaker proxy semantic abstractions that are less well represented in LLM training sets. This means we get arbitrarily complex SQLs to parse and transform.

  2. There are many different SQL dialects, each with its own annoying little differences.

  3. SQLs can be recursive and very large.

  4. The full list of transformations and verifications requires multiple SQL decompositions, re-compositions, namespace lookups and manipulations. This can easily become a CPU bottleneck and add to the end-to-end query latency. We need to constantly monitor and optimize the transformation performance.

Doing these post-transformations accurately and efficiently is key to agentic data analytics and data presentation. Generating the SQL text through correct AI context management and generation techniques is just the first phase of the problem.

Once the SQL is in WisdomAI, it goes through a long journey before it hits a warehouse. It is a deep stack with complex algorithmic and systems problems. This is what makes the WisdomAI Analytics Harness the most advanced in terms of power and enterprise-grade governance.

If you want to be a part of what we’re building at WisdomAI, check out our open roles and apply today.

Guilherme Menezes

Guilherme Menezes

Co-Founder and Chief Architect

Latest Blog

Latest Blog

Insights at your fingertips with AI-powered analytics

Insights at your fingertips with AI-powered analytics

Insights at your fingertips with AI-powered analytics

Insights at your fingertips with AI-powered analytics