OriginChainDB docs
examples · mysql · 4 / 4

4. Reflection: what the catalog will answer

← MySQL examples
what this does

Shows 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.

answered

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';
refused
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.

keeping an ORM on the answered half
// 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
decide before you adopt

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.