Your Linear backlog,
as SQL tables.
This demo shows ChalkSQL querying issues, projects and teams in Linear. ChalkSQL reads them as tables, turns your WHERE clause into Linear's own GraphQL filter, and joins the open issues with your helpdesk or warehouse in the same query.
Connect a SQL filter to the request Linear receives
The fictional workspace makes both the source request and the returned rows inspectable.
Try this experiment · expected results
1Run the default query
Choose Urgent work in flight and inspect the SQL predicates and request panel.
Expected: Team, priority, and workflow filters appear in the request sent to the example Linear API.
2Compare the returned rows
Read the result, then choose Bugs by revenue at stake.
Expected: The join combines Linear issues with support data; inspect which work stays in ChalkSQL.
Results appear here.
The team, an IN list on priority and the workflow state become one IssueFilter, so Linear only returns the five matching issues.
Run a query to see the requests.
The workspace belongs to Fernhill, a fictional analytics company. Its teams, projects and issues are served by a stand-in for Linear's GraphQL API (the issues, projects and teams queries, their filters and cursor pagination), so the exact requests are visible. The connector does not depend on the stand-in: point it at api.linear.app with an API key and it reads a real workspace. ChalkSQL and the connector run live on a Chalk scaling group.
Built on Chalk
ChalkSQL reads the source through its connector, pushes supported work to that source, and runs the remaining SQL over the returned rows.
Issues become a table
Register a Linear API key and linear.issues, linear.projects and linear.teams appear in the catalog, with state, priority, estimate, assignee, labels, project and dates as typed columns.
WHERE becomes an IssueFilter
Before the scan runs, the optimizer offers it the query's predicates. The ones Linear can evaluate go into the GraphQL query's filter variable, so Linear only returns the issues you asked for.
SQL does the rest
Joins with your helpdesk or warehouse, aggregates, date math and anything Linear cannot evaluate run in ChalkSQL. Results stream in a page at a time by following Linear's cursors.
Use ordinary SQL on returned rows
ChalkSQL applies the remaining joins, grouping, and sorting to the rows returned by the connector. The request panel shows which filters the source received.
A Linear source in one catalog call
The connector is a ChalkSQL schema provider. Each table is a pushdown-capable batch function over Linear's GraphQL API that translates SQL predicates into the query's filter variable and pages with first and after.
Register it once and Linear is queryable from anywhere ChalkSQL runs, joined with anything else in the catalog.
from linear_chalksql import LinearClient, LinearSchemaProvider, RequestLog, register_client
register_client(
"workspace",
LinearClient("https://api.linear.app/graphql", api_key=LINEAR_API_KEY, log=RequestLog()),
)
# linear.issues, linear.projects and linear.teams.
catalog.register_schema_provider("linear", LinearSchemaProvider("workspace"))Implementation details
How the example works
Issues become a table
Register a Linear API key and linear.issues, linear.projects and linear.teams appear in the catalog, with state, priority, estimate, assignee, labels, project and dates as typed columns.
WHERE becomes an IssueFilter
Before the scan runs, the optimizer offers it the query's predicates. The ones Linear can evaluate go into the GraphQL query's filter variable, so Linear only returns the issues you asked for.
SQL does the rest
Joins with your helpdesk or warehouse, aggregates, date math and anything Linear cannot evaluate run in ChalkSQL. Results stream in a page at a time by following Linear's cursors.
SQL behavior and pushdown rules
Numbers and dates
=, <, <=, > and >= on priority, estimate, due_date, created_at and completed_at become Linear's eq, lt, lte, gt and gte. IN becomes Linear's in. Exact, so ChalkSQL drops them.
Text
= and LIKE 'x%', '%x' or '%x%' on a title become eq, startsWith, endsWith and contains. Linear's string comparators are case-sensitive, like SQL's, so these are exact too.
Relations
state, team, assignee and project become nested filters such as { state: { type: { eq } } }. IS NULL and IS NOT NULL become { assignee: { null: true } }.
Labels
contains(labels, 'bug') becomes { labels: { some: { name: { eq: 'bug' } } } }, matched against the issue's label set.
<> and NOT IN
These become neq and nin to narrow the scan, but SQL drops NULLs and an API may keep them, so ChalkSQL re-checks the rows that come back.
LIMIT and paging
A LIMIT with no ORDER BY becomes first, and the scan stops once it has enough rows. Otherwise it follows endCursor, 100 issues per page.
Query the tools your team already uses
Linear, Notion, your warehouse and your databases in one SQL query. Talk to an engineer about the sources you want to join.