Visitar URL original
feat(review): let the AI review read and search the synced schema by h3n4l · Pull Request #21546 · bytebase/bytebase · GitHub
Skip to content

feat(review): let the AI review read and search the synced schema - #21546

Draft
h3n4l wants to merge 1 commit into
mainfrom
claude/ai-review-tools
Draft

h3n4l wants to merge 1 commit into
mainfrom
claude/ai-review-tools

Conversation

@h3n4l

@h3n4l h3n4l commented Sep 29, 2026

Copy link
Copy Markdown
Member

What

The AI review judged a change from the prompt alone: the target facts and the statements. This PR gives the model two tools over the synced schema of the database under review, so a finding can rest on a row count or on a view that reads the column.

  • search({text, schema, from}) finds the objects whose name or definition contains the text, without regard to case. It answers "what depends on this table".
  • read({objects: [{schema, name}], from}) returns the definition and statistics of the objects of up to 20 names. A table comes with its columns, indexes, constraints, and triggers, and with its row count, data size, and index size.

Part of BYT-9846. Follows #21523, where the executor ran without tools.

How

  • catalog.go holds the two tools. They take the schema proto the executor already loads for the target facts. They read nothing live and they make no store reads.
  • catalog_definition.go builds the definitions. A definition is what the renderer in backend/plugin/schema writes, the same text the product shows a user. A renderer writes a schema dump, so it leaves parts out: the MySQL one writes no triggers, and the PostgreSQL one skips a trigger an extension owns and writes a bare table when the sync holds no columns. The tools add such a part. The test is a second rendering without the part, and an equal result means the part was left out. An engine with no renderer gets a plain listing with every part.
  • Event triggers and extensions belong to the database, not to a schema, and are objects too.
  • A table with no statistics synced comes without statistics. Zeros would say the table is empty.
  • A result is one JSON object, so text from the database stays inside string values.
  • A result over 32 KiB is cut and carries next_from. The model repeats the call with from set to it. For read the cursor is a position in the definitions laid end to end, so every overload of a function can be reached. A cut falls behind a line break and never inside a character.
  • A name returns every object of that name. An exact schema and name win over ones that differ in case.
  • A definition is rendered on its first use. A read renders only what it returns, and a search keeps its matches for the next page.
  • Arguments the model got wrong come back as text it can correct. Only a failure of the tool itself fails the review.
  • AIReviewExecutor passes the tools in place of NoTools, which is removed.

Tests

  • catalog_test.go covers PostgreSQL, MySQL, and an engine with no renderer. It covers search by column, trigger, foreign key, and enum value, name lookup, schemas that differ in case, overloads, every comment the sync stores, the parts a dump leaves out, and bad arguments. The paging tests follow next_from to the end and compare the joined text with the source.
  • model_ai_test.go uses the real tools in place of the canned catalog.
  • review_run_lifecycle_test.go creates a table in the target database and syncs it. The stub model calls read, and the test asserts the result carries that table.
  • Live run against Gemini, not part of CI: the model called search and read, then raised both expected findings, with the row count and the dependent view as evidence.
  • Cost, measured: the first search over 20,000 PostgreSQL tables with comments, two indexes, and a foreign key each takes 0.3 s. A later search takes 40 ms.

Known limits

  • Statistics are per table. Size per index needs the sync to collect it first.
  • A field inside one item that a renderer does not write, such as the visibility of one index, stays unwritten.
  • Each review of a run builds its own object list.

🤖 Generated with Claude Code

The AI review judged a change from the prompt alone. It now gets two
tools over the synced schema of the database under review. search finds
the objects whose name or definition contains a text. read returns the
definition and statistics of the objects of up to 20 names.

The tools read the synced metadata and nothing live. A definition is
what the engine's renderer writes, with the parts it leaves out added:
a renderer writes a schema dump, so it can leave out triggers,
comments, or the collections of a table it has no columns for. A part
is left out when the object renders the same without it. An engine with
no renderer gets a plain listing.

A result over 32 KiB is cut and carries next_from. The cursor of a read
is a position in the definitions laid end to end, so every overload of
a function can be reached, and a cut never falls inside a character.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant