Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 45 additions & 9 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ In `packages/core/src`, a module uses another only through its `index.ts`, never
- `parser/`: `check()`, `roles()`, and the Expected set at a position, which completion uses.
- `highlight/`: `highlight()`.
- `format/`: `format()`.
- `complete/`: `complete()`, `describe()`, `engineArgument()` and `functionArgument()`.
- `complete/`: `complete()`, `describe()`, `engineArgument()`, `functionArgument()`, `parameterHints()` and `keywordDocumentation()`.
- `options/`: `checkOptions()`, and the settings, codecs and other options that completion offers.
- `names/`: `definition()`, `references()`, `prepareRename()` and `rename()`.
- `names/`: `definition()`, `references()`, `prepareRename()` and `rename()`, and `objects()`, `objectReferences()` and `objectDefinitions()` across files.
- `structure/`: `outline()`, `foldingRanges()` and `selectionRanges()`.
- `generated/`: lists from ClickHouse: keywords, data types, privileges, and the functions, settings, table engines,
formats, table functions, combinators and time zones that completion offers.
Expand Down Expand Up @@ -77,21 +77,43 @@ A layer apart from `check()`, which it never changes: it looks only at the state
`backup`, ...); names analysis skips these marks. `options/catalog.ts` gives the settings each place takes, and
ClickHouse's message for a name it does not take.
2. Each `name = value` is checked by name, and its literal by the conversions of `src/Core/SettingsFields.cpp`
(`options/values.ts`): numbers in range, strings that parse, booleans, enums and their lists, one character, maps
and time zones. DEFAULT, query parameters, `param_` and `custom_` names are left alone.
(`options/values.ts`): numbers in range, strings that parse, booleans, enums and their lists, one character, maps,
time zones, URIs and the version of `compatibility`; a map given to another type gets ClickHouse's message for it.
DEFAULT, query parameters, `param_` and `custom_` names are left alone.
3. The roles find `CODEC(...)`, `INDEX ... TYPE`, `STATISTICS`, `FORMAT` and `COMPRESSION`. A parameter of a codec or
index type is checked against the values that ClickHouse was asked about: a number between two probes with the same
verdict gets that verdict, any other is left alone.
4. An error is what ClickHouse refuses before the statement runs, whatever its server. What a setting of the server or
verdict gets that verdict, any other is left alone. The `name = value` arguments of the `text` index are checked by
name. A codec is checked against the types that the column's type holds, through Nullable, LowCardinality, Array,
Map and Tuple, when each is a type that ClickHouse was asked about with that codec; a column without a type written
is left alone. The `LEVEL` of `INTO OUTFILE` is checked against the range of its compression method.
4. After `SET default_table_engine = 'None'`, a `CREATE TABLE` without `ENGINE` that does not take one from `AS`
another table is an error, as ClickHouse refuses it with ENGINE_REQUIRED.
5. An error is what ClickHouse refuses before the statement runs, whatever its server. What a setting of the server or
session can allow (`allow_suspicious_codecs`, the settings of experimental codecs) and what fails only as the
statement runs (a compression method) is a warning. `ATTACH` is not checked, as ClickHouse does not check it again.

## Quick fixes

A diagnostic that knows the answer carries `fixes`, each a title and the edits that apply it (`options/fixes.ts`):

- The names within a few typos of an unknown setting, codec, index or statistics type, format, compression method,
enum value or test hint error name, found as ClickHouse's `NamePrompter` finds them, closest first. A codec or index
type must take the parameters written, and a setting the value written; for settings only the closest are kept.
- The keyword of check()'s "Maybe you meant", in the case of the word, kept only when the statement then passes check().
- A number in quotes for a setting of one character, and `ENGINE = MergeTree`, with `ORDER BY tuple()` when the
table has no ORDER BY or PRIMARY KEY, for ENGINE_REQUIRED.
- `messageFixes()` reads the names of "Maybe you meant" in an error of the server for the extension's server check.

The fix that is closer than all the others is the preferred one. `npm run oracle:fixes` applies every fix to
generated statements and to the sample of the oracle and runs the results in `clickhouse local`.

The catalog comes from ClickHouse: `scripts/generate-catalog.ts` asks `system.settings` and the enum values of each
setting (from ClickHouse's "Must be one of" for a value no enum has), and `scripts/generate-options.ts` reads
`system.merge_tree_settings`, `system.codecs`, `system.data_skipping_index_types`, `system.database_engines`, the
lists of settings that the sources declare for the other engines, BACKUP and RESTORE, and the docs of EXPLAIN. It
asks a binary, in `clickhouse local`, which names each engine takes, which values each enum, codec parameter and index
parameter takes, and the messages for the others, so a new release updates all of it.
lists of settings that the sources declare for the other engines, BACKUP and RESTORE, the argument names of the text
index, and the docs of EXPLAIN. It asks a binary, in `clickhouse local`, which names each engine takes, which values
each enum, codec parameter and index parameter takes, which data types each codec refuses, which levels each
compression method takes, and the messages for the others, so a new release updates all of it.

## roles() and highlight()

Expand Down Expand Up @@ -162,6 +184,18 @@ In the brackets of a function, the suggestions for the argument at the cursor co
the statement makes and of the tables it reads in the schema follow, those whose type fits the documented types
of the argument first.

`parameterHints()` names the argument of each call with two arguments or more, in the statements that parse and where
the parser reads the name as a function or an engine, by the same reading as `functionArgument()` and
`engineArgument()` at the start of the argument. An argument that is a name equal to the parameter, one that the
syntax leaves open and the arguments of a repeated parameter get no name.

`keywordDocumentation()` gives the section of ClickHouse's documentation of the SYSTEM command at an offset, by the
longest command that the words after SYSTEM start with, and in `CREATE` and `ALTER` of a user, role, quota, row policy
or settings profile, of the clause whose keywords are there, or the statement's syntax for another keyword.
`scripts/generate-statements.ts` reads them from `docs/reference/statements`: the commands from the headings of
`system.mdx` and the forms its syntax adds, the clauses from the sections named after them and the paragraphs that
start with them.

In a list of settings, `options/complete.ts` reads from the words before it which place it is (a query, `SET`, the
engine of `ENGINE = Name ... SETTINGS`, a database, a column, `MODIFY SETTING`, `EXPLAIN kind`, `BACKUP`, ...) and
offers that place's settings, its own before those of queries, and after `name =` the values of an enum or a boolean.
Expand Down Expand Up @@ -229,6 +263,8 @@ In `packages/vscode/src`:
- `selection.ts`: Expand and Shrink Selection from `selectionRanges()`, with the `ParseCache` of the document.
- `format.ts`: Format Document and Format Selection through `format()`, with the editor's indentation. Format Selection
matches the units of `split()` in the text and in its formatted copy, and replaces only the ones the selection touches.
- `inlay.ts`: inlay hints, off by default, from `parameterHints()` for the statements on the screen, and the type of
each `param_name` on it from the `{name:Type}` of the document.
- `complete.ts`, `hover.ts`, `signature.ts`: completion, hover and signature help through `complete()`, `describe()`
and, in the brackets of an engine or a function, `engineArgument()` or `functionArgument()`;
hover takes the role of the word from the parser where completion does not tell what it is.
Expand Down
7 changes: 6 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ npm run oracle:format -- --clickhouse <clickhouse> --corpus <ClickHouse checkout
npm run oracle:rename -- --clickhouse <clickhouse> --corpus <ClickHouse checkout>/tests/queries/0_stateless
npm run oracle:arguments -- --clickhouse <clickhouse> --corpus <ClickHouse checkout>/tests/queries/0_stateless
npm run oracle:options -- --clickhouse <clickhouse> --corpus <ClickHouse checkout>/tests/queries/0_stateless
npm run oracle:fixes -- --clickhouse <clickhouse>
```

The second command labels every statement of the tests with that binary and compares `check()` with it. The third
Expand All @@ -44,7 +45,9 @@ whole, as LF and as CRLF text. The fourth renames the names of each SELECT that
and checks that the renamed query gives the same result. The fifth checks what completion offers in the arguments of
functions against the arguments that the tests write, and runs each suggestion in a call. The sixth runs each statement of the tests that `checkOptions()` flags in
`clickhouse local`, compares its checks of settings, codecs and index types with ClickHouse on generated values, and
runs every option that completion offers. `npm test` fails when the sample's rates fall below
runs every option that completion offers. The seventh applies every quick fix to statements with typos of the
names of the catalogs, wrong values, CREATE TABLE without ENGINE, test hints with unknown error names and the
invalid statements of the sample, and counts the fixed statements that ClickHouse takes. `npm test` fails when the sample's rates fall below
`oracle/thresholds.json`; raise them when `check()` gets better. [oracle/README.md](oracle/README.md) describes the
sample and how to rebuild it.

Expand All @@ -56,6 +59,8 @@ The lists that come from ClickHouse are generated; do not edit them by hand.
- `npx tsx scripts/generate-catalog.ts --clickhouse <clickhouse>`: the functions, settings, table engines, formats,
table functions, combinators and time zones that completion offers. Signatures missing from the server metadata
are maintained in `scripts/catalog-signatures.ts`.
- `npx tsx scripts/generate-statements.ts --docs <ClickHouse checkout>/docs/reference`: the documentation of SYSTEM commands
and of the clauses of the access statements that hover shows, in `packages/core/src/generated/statements.ts`.
- `npx tsx scripts/generate-errors.ts --clickhouse <clickhouse>` in `packages/vscode`: the error codes of test hints
in `packages/vscode/src/generated/errors.ts`.
- `npx tsx scripts/generate-readme.ts` in `packages/vscode`: the settings and commands of its README, from its
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ A VS Code extension and a TypeScript library that read [ClickHouse](https://gith
- **Highlighting**: keywords, functions, types and names get their colours from how the parser reads them.
- **Error checking**: the syntax errors that ClickHouse would report, shown as you type.
- **Options**: settings, engine and database settings, codecs, index and statistics types, formats and the settings of EXPLAIN and BACKUP completed and documented, and their names and values checked as ClickHouse checks them.
- **Quick fixes**: the name or keyword that a typo is closest to, the server's "Maybe you meant" hints, and a missing `ENGINE` where ClickHouse requires one.
- **Formatting**: queries laid out as `clickhouse format` does.
- **Autocomplete**: keywords, functions, types, settings, engines and formats that fit where you type.
- **Engine arguments**: in `ENGINE = Name(...)`, what the argument at the cursor takes, and the engine's parameters as you type.
- **Function arguments**: what ClickHouse's documentation says the argument at the cursor takes, such as a unit, a data type, a time zone, a format or a JSONPath, and in `JSON(...)` its parameters.
- **Outline**: each statement with its CTEs and columns, in the Outline view and breadcrumbs.
- **Folding**: statements, subqueries and comments of several lines, and `-- #region` blocks.
- **Expand Selection**: grows from a word to its expression, call, clause, subquery and statement.
- **Hover**: ClickHouse's documentation of functions, settings, engines, formats, SYSTEM commands and the clauses of the statements that make and change users, roles, quotas, row policies and settings profiles.
- **Inlay hints** (optional): the names of the parameters before the arguments of calls, such as `dateDiff(unit: 'day', ...)`.
- **Go to definition and rename**: aliases, CTEs, table aliases and lambda and query parameters, scoped as ClickHouse scopes them.
- **Workspace symbols**: the tables, views, dictionaries, functions and databases that the CREATE statements of the folder make, and go to definition and references of a table from the queries of any file.
- **Server check** (optional): your own ClickHouse server checks the names, functions and types in your queries.

## Use it in VS Code
Expand All @@ -29,7 +33,7 @@ To build it yourself instead (needs Node.js 22 or newer):
git clone https://github.com/valerypetrov/clickhouse-sql-syntax.git
cd clickhouse-sql-syntax
npm install && npm run build && npm run package:vscode
code --install-extension packages/vscode/clickhouse-sql-0.4.0.vsix
code --install-extension packages/vscode/clickhouse-sql-0.5.0.vsix
```

## Use the library
Expand Down
3 changes: 2 additions & 1 deletion oracle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
"oracle:rename": "tsx src/rename-oracle.ts",
"oracle:arguments": "tsx src/arguments-oracle.ts",
"oracle:options": "tsx src/options-oracle.ts",
"oracle:fixes": "tsx src/fixes-oracle.ts",
"typecheck": "tsc -p tsconfig.json",
"test": "npm run typecheck && tsx --test \"test/**/*.test.ts\""
},
"dependencies": {
"clickhouse-sql-syntax": "0.4.0"
"clickhouse-sql-syntax": "0.5.0"
}
}
Loading
Loading