4. Reflection: what the catalog will answer
← MySQL examplesShows exactly where the metadata boundary sits, because this is the thing most likely to decide whether your tool works. Metadata is split: the information_schema views are answered, and every SHOW form is refused. A tool that reflects through the first half gets somewhere; one that reflects through the second does not.
Five views, served by the same shared catalog the other wire protocols read: tables, columns, table_constraints, key_column_usage, referential_constraints.
-- List the tables in a schema. SELECT table_name FROM information_schema.tables WHERE table_schema = 'shop'; -- Describe one table's columns. SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_schema = 'shop' AND table_name = 'orders'; -- Constraints, and the columns they cover. SELECT constraint_name, constraint_type FROM information_schema.table_constraints WHERE table_name = 'orders'; SELECT constraint_name, column_name FROM information_schema.key_column_usage WHERE table_name = 'orders';
SHOW TABLES; -- refused SHOW DATABASES; -- refused SHOW COLUMNS FROM orders; -- refused SHOW CREATE TABLE orders; -- refused SHOW INDEX FROM orders; -- refused SHOW WARNINGS; -- refused SHOW VARIABLES LIKE 'sql_mode'; -- refused
The refusal is deliberate, and it is the safer of the two options. The shared front door
carries a compatibility shim for a different protocol that answers any SHOW x with a single fabricated row reading x = 'on'. Left
alone, SHOW TABLES would return that row: a confident,
wrong answer. Refusing at the dialect boundary turns it into an error you can see.
// Safe: you tell the ORM the shape, it never asks the database.
const Order = sequelize.define(
"Order",
{
id: { type: DataTypes.STRING, primaryKey: true },
customer: DataTypes.STRING,
total_cents: DataTypes.INTEGER,
status: DataTypes.STRING,
},
{ tableName: "orders", timestamps: false, freezeTableName: true },
);
// Not safe on this listener - each of these introspects with SHOW:
// await sequelize.sync();
// await sequelize.getQueryInterface().describeTable("orders");
// await sequelize.getQueryInterface().showIndex("orders");
// Also not available: associations. Model the join in your query instead of
// asking the ORM to follow a relation for you.
// Order.belongsTo(Customer); // will not load Because reflection is split and associations do not load, this listener suits an application whose tables are declared in code and whose queries touch one table at a time. It does not suit one that models a domain with relations, and no amount of configuration changes that today. If you need relations, use the SQL endpoint or the PostgreSQL wire, both of which carry the full surface today.
MySQL is a registered trademark of Oracle Corporation and/or its affiliates. OriginChainDB is not affiliated with, endorsed by, or sponsored by Oracle Corporation. OriginChainDB implements a compatible wire protocol so that existing MySQL clients can connect to it; it does not distribute MySQL software.