Skip to content

Language record

SQL

SQL is read as the schema it declares and the calls it makes: tables, columns, views, indexes, stored functions, triggers, types and schemas each get an identity, a foreign key is a reference to another table, and a trigger that executes a function — or a call to a function the database does not provide — is a call edge.

.sql · 1 registry id · 10 of 14 relationship types

The registry row this page is generated from

Read at render time from the same family row the register reads, so nothing in this block can disagree with it.

Extensions
.sql
Registry names
sql
Recorded symbols
tables · views · procedures · columns

Relationship types this analyzer constructs

10 of 14 constructed, read from this analyzer's source and re-derived by the languages gate. Each row below is one of the engine's types, in the engine's own order.

Relationship typeConstructed
callsconstructed by this analyzer
extendsconstructed by this analyzer
implementsconstructed by this analyzer
usesconstructed by this analyzer
importsconstructed by this analyzer
exportsconstructed by this analyzer
containsconstructed by this analyzer
referencesconstructed by this analyzer
overridesconstructed by this analyzer
instantiatesconstructed by this analyzer
decoratesnot constructed
rendersnot constructed
mixes_innot constructed
part_ofnot constructed

10 constructed, 4 not constructed. This family's completeness record does not agree with the analyzer-source derivation on the emitted vocabulary, so no per-type ruling is claimed for those absences; they are shown as not constructed and their absence is a derived fact, not a format claim. The register explains what each label means.

What this analyzer does not resolve

  • Procedural bodies are where most declarations sit, and the grammar is the limit. On the versioned PostgreSQL extension corpus, distinct-name function recall is 1,004 of 1,170 (85.8%), 282 of 387 files still carry at least one parse error, and 56 of those files publish no symbols at all. The name-based figure is the one to use, because a count ratio measures how often a function is re-declared across version scripts rather than how many were found.
  • Dynamic SQL is unresolved on purpose. The recovery pass that reads EXECUTE 'CREATE TRIGGER …' recovers the KIND of the declaration and cannot recover its NAME, because 94% of the extension corpus's EXECUTE literals are concatenated fragments whose identifier is computed by the database at run time. It invents no name to fill the gap.
  • A call to something the database provides is not a call into your code. Names like generate_series, jsonb_build_object, current_setting and uuid_generate_v4 are held in a builtin list and filtered, because an edge to one resolves to nothing and would show a call into a table name. What is left unresolvable is bucketed — catalog, information_schema, implicit schema, platform — and the buckets are published in the file's metadata so an unresolved edge can be read as a fact rather than guessed at.

Every line above was written against SQL’s own analyzer module and is named against a construct in it, so it can be checked against the source. Nothing here is inherited from a template, or from another language’s page.

Where you meet it in a repository

Recognised by extension — .sql. Everything below is about where those files actually sit in a working repository.

  • Migrations are the interesting half — the same table name appears in every schema revision, so the history is queryable, and an index is recorded as owned by the table it indexes so the containment edge and the reference edge point the same way.
  • A view, a materialised view and a table are all class symbols, and a stored function, a procedure and a trigger are all function symbols. The distinction survives in metadata, so anything that has to tell a view from a table reads the declaration rather than the kind.
  • Anonymous queries have no owner of their own and their edges are sourced from the file, so a SELECT in a migration is still attached to the file it was written in. A CTE name, by contrast, is scoped to its own statement: a name declared in one WITH cannot satisfy a reference in the next, and leaking it would publish a table that does not exist.

Questions this index answers

Phrased as retrievals, because that is what an index can honestly do: it holds the symbols and the edges between them, and hands them back with the evidence attached.

  1. Which columns does this table actually have, and which of them are keys?
  2. Which trigger runs on this table, and which function does it execute?
  3. Where is this view defined, and which tables does it select from?
  4. Which foreign keys point at this table from somewhere else?

What the analyzer sees in code like this

A table with a key column, the function a trigger runs, and the trigger's call edge
CREATE TABLE audit_log (                -- bb records: table audit_log
  id         BIGSERIAL PRIMARY KEY,    -- bb records: column id
  actor      TEXT NOT NULL             -- bb records: column actor
);

CREATE FUNCTION archive_actor() RETURNS trigger AS $$
BEGIN
  RETURN NEW;                          -- the body is ordinary SQL, which is the only shape that parses
END; $$ LANGUAGE plpgsql;

CREATE TRIGGER audit_after BEFORE INSERT ON audit_log
  FOR EACH ROW EXECUTE FUNCTION archive_actor();   -- bb records: calls -> archive_actor

Symbols are stored with the file they came from and the bytes they span, so a hit points at a line rather than at a guess. The annotations in the sample are commentary for the reader, not strings the index would store.

Languages that turn up in the same repository

Web, data & config — the count beside each name is how many relationship types that family’s analyzer constructs.

The extensions, registry names, recorded symbols and relationship types above are the parser registry row for SQL, read while the page rendered — the same row the register reads, so the two surfaces cannot tell two stories. Every relationship type listed as constructed appears in src/ast/real-*, the analyzer modules bb ships. bb 0.1.0 answers from a local store over 50 languages (53 registry ids, three of them aliases). There is no benchmark on this page: every claim here is one you can go and read in the source.