Skip to content

Commit 15548b9

Browse files
SangJunBakclaude
andcommitted
test: add mz_tables and mz_views lockdown slts (SQL-150)
mz_tables and mz_views became BuiltinMaterializedViews over mz_internal.mz_catalog_raw, deriving every column from durable catalog JSON, but the conversion added no test file. Every earlier conversion (mz_indexes, mz_audit_events, mz_postgres_sources) got one. Follows the established lockdown shape: one section per union branch, plus the temporary-item sentinel schema id, the exactly-once property across the user and builtin branches, and the ASSERT NOT NULL columns. Two checks are independent of the MV rather than golden values: oid is compared against a regclass cast, which resolves through the in-memory catalog, and mz_views.definition is compared against the definition of a view planned from it, so the rendering is verified to be a fixed point end to end. create_sql cannot be compared against SHOW CREATE, which humanizes item ids and pretty-prints by design. Also pins the one known difference from the old builtin tables: mz_builtin_views cannot list itself, so it is the single builtin view absent from mz_views. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 147685e commit 15548b9

2 files changed

Lines changed: 489 additions & 0 deletions

File tree

test/sqllogictest/mz_tables.slt

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
# Copyright Materialize, Inc. and contributors. All rights reserved.
2+
#
3+
# Use of this software is governed by the Business Source License
4+
# included in the LICENSE file at the root of this repository.
5+
#
6+
# As of the Change Date specified in that file, in accordance with
7+
# the Business Source License, use of this software will be governed
8+
# by the Apache License, Version 2.0.
9+
10+
# Behavioural tests for mz_catalog.mz_tables. It is a BuiltinMaterializedView
11+
# over mz_internal.mz_catalog_raw (see MZ_TABLES in
12+
# src/catalog/src/builtin/mz_catalog.rs) with two union branches, user tables
13+
# and builtin tables, and it derives every column from the durable catalog JSON
14+
# through parse_catalog_id, parse_catalog_privileges, redact_sql and
15+
# parse_catalog_create_sql (src/expr/src/scalar/func/impls/jsonb.rs).
16+
#
17+
# Before that it was a BuiltinTable populated by pack_table_update in the
18+
# adapter, so the values pinned here are a compatibility surface:
19+
# information_schema.tables, pg_tables and pg_class all read through it.
20+
#
21+
# Assertions filter by object name rather than counting rows, so the file also
22+
# holds under --auto-index-selects, which creates extra views.
23+
24+
mode cockroach
25+
26+
# Stable object ids, so create_sql can name dependencies by id.
27+
reset-server
28+
29+
# --- user_tables branch -------------------------------------------------------
30+
31+
# `t` is the first object created after the reset, so it is u1 and create_sql
32+
# below can name it.
33+
statement ok
34+
CREATE TABLE t (a int, b text NOT NULL)
35+
36+
query T
37+
SELECT id FROM mz_tables WHERE name = 't'
38+
----
39+
u1
40+
41+
query T
42+
SELECT schema_id = (SELECT id FROM mz_schemas WHERE name = 'public' AND database_id IS NOT NULL)
43+
FROM mz_tables WHERE name = 't'
44+
----
45+
true
46+
47+
query T
48+
SELECT owner_id = (SELECT id FROM mz_roles WHERE name = 'materialize')
49+
FROM mz_tables WHERE name = 't'
50+
----
51+
true
52+
53+
query T multiline
54+
SELECT create_sql FROM mz_tables WHERE name = 't'
55+
----
56+
CREATE TABLE "materialize"."public"."t" ("a" [s20 AS "pg_catalog"."int4"], "b" [s46 AS "pg_catalog"."text"] NOT NULL)
57+
EOF
58+
59+
query T multiline
60+
SELECT redacted_create_sql FROM mz_tables WHERE name = 't'
61+
----
62+
CREATE TABLE materialize.public.t (a [s20 AS pg_catalog.int4], b [s46 AS pg_catalog.text] NOT NULL)
63+
EOF
64+
65+
# A table with no source omits `source_id` from the parsed create_sql, so the
66+
# column must be NULL rather than absent or empty.
67+
query T
68+
SELECT source_id IS NULL FROM mz_tables WHERE name = 't'
69+
----
70+
true
71+
72+
# --- Cross-check against the in-memory catalog --------------------------------
73+
74+
# The oid column is read out of the durable JSON, while a regclass cast resolves
75+
# the name through the in-memory catalog. Two independent paths that must agree.
76+
#
77+
# NB create_sql cannot be compared against SHOW CREATE TABLE the same way: SHOW
78+
# humanizes item ids back to names and pretty-prints, so it is deliberately not
79+
# the stored string.
80+
query T
81+
SELECT oid = 't'::regclass::oid FROM mz_tables WHERE name = 't'
82+
----
83+
true
84+
85+
# --- source_id, for a table created from a source -----------------------------
86+
87+
statement ok
88+
CREATE SOURCE lg FROM LOAD GENERATOR COUNTER
89+
90+
statement ok
91+
CREATE TABLE lg_tbl FROM SOURCE lg (REFERENCE counter)
92+
93+
query T
94+
SELECT source_id = (SELECT id FROM mz_sources WHERE name = 'lg')
95+
FROM mz_tables WHERE name = 'lg_tbl'
96+
----
97+
true
98+
99+
# --- Temporary tables ---------------------------------------------------------
100+
101+
# Temporary items are durable catalog items tagged with their owning session,
102+
# parented to a sentinel schema id shared by every session. The MV maps that
103+
# sentinel to schema_id '0', which is what the old SchemaSpecifier::Temporary
104+
# populator printed (src/sql/src/names.rs).
105+
106+
statement ok
107+
CREATE TEMP TABLE tt (x int)
108+
109+
query TTT
110+
SELECT id LIKE 'u%', schema_id, create_sql IS NOT NULL FROM mz_tables WHERE name = 'tt'
111+
----
112+
true 0 true
113+
114+
# Two sessions may each hold a temporary table of the same name: name
115+
# uniqueness is scoped by the owning session. Both rows show up here, since
116+
# mz_tables reports every item and per-session visibility lives in name
117+
# resolution, not in this MV.
118+
simple conn=other
119+
CREATE TEMP TABLE tt (y text);
120+
----
121+
COMPLETE 0
122+
123+
query I
124+
SELECT count(*) FROM mz_tables WHERE name = 'tt'
125+
----
126+
2
127+
128+
query T
129+
SELECT array_agg(DISTINCT schema_id) FROM mz_tables WHERE name = 'tt'
130+
----
131+
{0}
132+
133+
# --- builtin_tables branch ----------------------------------------------------
134+
135+
query TTTT
136+
SELECT id LIKE 's%', owner_id, create_sql IS NULL, source_id IS NULL
137+
FROM mz_tables WHERE name = 'mz_kafka_sinks'
138+
----
139+
true s1 true true
140+
141+
query T
142+
SELECT schema_id = (SELECT id FROM mz_schemas WHERE name = 'mz_catalog' AND database_id IS NULL)
143+
FROM mz_tables WHERE name = 'mz_kafka_sinks'
144+
----
145+
true
146+
147+
# Exactly once: the user and builtin branches must not both claim a row.
148+
query I
149+
SELECT count(*) FROM mz_tables WHERE name = 'mz_kafka_sinks'
150+
----
151+
1
152+
153+
# Every builtin table the catalog generates must be reported.
154+
query T
155+
SELECT array_agg(name ORDER BY name) FROM (
156+
SELECT name FROM mz_internal.mz_builtin_tables
157+
EXCEPT
158+
SELECT name FROM mz_tables WHERE id LIKE 's%'
159+
)
160+
----
161+
NULL
162+
163+
# ...and nothing else: every builtin row traces back to the reporter.
164+
query T
165+
SELECT array_agg(name ORDER BY name) FROM (
166+
SELECT name FROM mz_tables WHERE id LIKE 's%'
167+
EXCEPT
168+
SELECT name FROM mz_internal.mz_builtin_tables
169+
)
170+
----
171+
NULL
172+
173+
# The reporter view backing this MV is itself a builtin view, reported through
174+
# mz_views with placeholder SQL. See mz_views.slt for the full contract.
175+
query I
176+
SELECT count(*) FROM mz_views WHERE name = 'mz_builtin_tables'
177+
----
178+
1
179+
180+
# --- Robustness over the whole catalog ----------------------------------------
181+
182+
# The MV runs parse_catalog_create_sql over every Item row in the catalog, in
183+
# its WHERE clause, so a single item whose create_sql the parser rejects makes
184+
# the entire relation unreadable rather than dropping one row. Create one item
185+
# of every kind reachable here and confirm the relation still resolves.
186+
187+
statement ok
188+
CREATE VIEW v AS SELECT a FROM t
189+
190+
statement ok
191+
CREATE MATERIALIZED VIEW mv AS SELECT count(*) FROM t
192+
193+
statement ok
194+
CREATE INDEX t_idx ON t (a)
195+
196+
statement ok
197+
CREATE TYPE ty AS LIST (ELEMENT TYPE = int4)
198+
199+
statement ok
200+
CREATE SECRET sec AS 'hunter2'
201+
202+
query T
203+
SELECT count(*) > 0 FROM mz_tables
204+
----
205+
true
206+
207+
# --- NOT NULL invariants ------------------------------------------------------
208+
209+
# The MV declares ASSERT NOT NULL for these columns.
210+
query I
211+
SELECT count(*)
212+
FROM mz_tables
213+
WHERE id IS NULL
214+
OR oid IS NULL
215+
OR schema_id IS NULL
216+
OR name IS NULL
217+
OR owner_id IS NULL
218+
OR privileges IS NULL
219+
----
220+
0
221+
222+
statement ok
223+
DROP TABLE t CASCADE

0 commit comments

Comments
 (0)