pingcap / pingcap/tidb

information_schema.VIEWS reports CASCADED instead of NONE for views without CHECK OPTION

Open
#71,252 4 comments 0 reactions 0 assignees View on GitHub
contribution first-time-contributor severity/moderate sig/sql-infra
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

```sql
CREATE TABLE t(a INT);

CREATE VIEW v_none AS SELECT * FROM t WHERE a > 1;
CREATE VIEW v_local AS SELECT * FROM t WHERE a > 1 WITH LOCAL CHECK OPTION;
CREATE VIEW v_cascaded AS SELECT * FROM t WHERE a > 1 WITH CASCADED CHECK OPTION;

SELECT TABLE_NAME, CHECK_OPTION
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN ('v_none', 'v_local', 'v_cascaded')
ORDER BY TABLE_NAME;
```

### 2. What did you expect to see? (Required)

The same values as MySQL 8.0.46, which returns `NONE` for the view created without a check option:

```text
+------------+--------------+
| TABLE_NAME | CHECK_OPTION |
+------------+--------------+
| v_cascaded | CASCADED |
| v_local | LOCAL |
| v_none | NONE |
+------------+--------------+
```

MySQL lists `NONE` among the possible `CHECK_OPTION` values of `INFORMATION_SCHEMA.VIEWS`, and returns it for the statements above.

TiDB's own `INFORMATION_SCHEMA.VIEWS` documentation also lists `NONE` as a possible `CHECK_OPTION` value, although its current example shows `CASCADED` for `CREATE VIEW test.v1 AS SELECT 1`, which has no check-option clause.

### 3. What did you see instead? (Required)

TiDB reports `CASCADED` for `v_none`:

```text
+------------+--------------+
| TABLE_NAME | CHECK_OPTION |
+------------+--------------+
| v_cascaded | CASCADED |
| v_local | LOCAL |
| v_none | CASCADED |
+------------+--------------+
```

As a result, a view created without a check-option clause is indistinguishable in `information_schema.VIEWS` from one created with an explicit `WITH CASCADED CHECK OPTION`.

This can affect schema-diff tools, ORMs, and other clients that use `information_schema.VIEWS` to reconstruct view metadata, because the original check-option state cannot be recovered from the catalog.

In my test, `SHOW CREATE VIEW` also omitted the check-option clause for all three views, so it did not provide a way to recover this distinction either.

Likely cause, from reading the code:

- `ast.ViewCheckOption` only defines `CheckOptionLocal` and `CheckOptionCascaded` in `pkg/parser/ast/model.go`. There is no value representing the absence of a check-option clause.
- The `CreateViewStmt` action in `pkg/parser/parser.y` therefore assigns `ast.CheckOptionCascaded` when the clause is absent.
- `BuildViewInfo` in `pkg/ddl/create_table.go` persists that value as `model.ViewInfo.CheckOption`, which is stored as `view_checkoption` in the table metadata.
- `pkg/executor/infoschema_reader.go` renders `model.ViewInfo.CheckOption` directly into the `CHECK_OPTION` column.

Fixing this likely requires representing "no check option" as a distinct persisted state. Existing metadata already stores both an omitted clause and an explicit `CASCADED` clause as the same value, so the original form cannot be reconstructed for views that already exist. Introducing a new persisted state would also require deciding how it should behave across upgrades and downgrades.

This is separate from #71248. That PR adds parser support for the unqualified `WITH CHECK OPTION` syntax, for which `CASCADED` is the correct value. This issue is about views created without any check-option clause at all.

### 4. What is your TiDB version? (Required)

```text
Release Version: v8.5.3
Edition: Community
Git Commit Hash: dc2548aac79a712265e831cff2a3a896bc0a5a38
Git Branch: HEAD
UTC Build Time: 2025-07-31 13:54:43
GoVersion: go1.23.8
Race Enabled: false
Check Table Before Drop: false
Store: unistore
```

Also reproduced on `master` built locally with `unistore`.

Contributor guide

Open the contributing guide

Research direction

Start with the CREATE VIEW action in pkg/parser/parser.y and ast.ViewCheckOption in pkg/parser/ast/model.go, then trace BuildViewInfo in pkg/ddl/create_table.go through pkg/executor/infoschema_reader.go. Reproduce the three SQL views from the issue and inspect existing metadata and compatibility tests. Done means INFORMATION_SCHEMA.VIEWS distinguishes no clause, LOCAL, and CASCADED without regressing metadata handling across upgrades or downgrades.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, sql
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.