Expand description
SQL DDL in the format-neutral model: a small CREATE TABLE subset.
parse reads a file of statements into a Schema of tables, one
per CREATE TABLE, each column a Field with its type as written
(VARCHAR(20), kept as the native type) and the
model’s type for it (string). It reads:
- column names and types, quoted (
"x",`x`,[x]) or not, with their parameters (NUMERIC(10, 2)), several words (DOUBLE PRECISION,TIMESTAMP WITH TIME ZONE) and arrays (INT[]); NOT NULLandNULL,DEFAULT(any expression, kept as written),PRIMARY KEY,UNIQUEandREFERENCES table (column), on a column or, for one or several columns, on the table (PRIMARY KEY (a, b),UNIQUE (a, b),FOREIGN KEY (a) REFERENCES t (x)), named withCONSTRAINT nameor not, and MySQL’sENUM('a', 'b')andCOMMENT;--and/* … */comments, PostgreSQL’s dollar-quoted strings ($$ … $$, a function body’s), and any number of statements, each ended by;or, in a script that leaves it out, by aGOline or theCREATEthat starts the next.
CHECK constraints, indexes, generated columns and other clauses are
skipped, as is every statement but CREATE TABLE (CREATE INDEX,
ALTER TABLE, INSERT, …); each skip is a Note with its line, so
nothing is dropped silently. Text that cannot be read (an unclosed
string, comment or parenthesis, a CREATE TABLE without a column list)
is a SqlError with its line. Input is bounded by MAX_INPUT,
MAX_STATEMENTS, MAX_TOKENS, MAX_COLUMNS and MAX_NESTING,
statements are read one at a time, and the reader never panics.
use rich_ext::schema::{sql, DataType};
let ddl = "
-- The people.
CREATE TABLE users (
id BIGINT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
team INT REFERENCES teams (id),
CHECK (email <> '')
);
CREATE INDEX users_email ON users (email);
";
let parsed = sql::parse(ddl).unwrap();
let users = parsed.schema.table("users").unwrap();
let email = users.field("email").unwrap();
assert_eq!(email.native_type(), Some("VARCHAR(255)"));
assert_eq!(email.data_type(), &DataType::String);
assert!(email.is_required() && email.is_unique());
assert_eq!(users.primary_key(), ["id"]);
assert_eq!(users.foreign_keys()[0].to_string(), "team → teams.id");
let notes: Vec<String> = parsed.notes.iter().map(ToString::to_string).collect();
assert_eq!(
notes,
[
"line 7: users: CHECK constraint skipped",
"line 9: CREATE INDEX statement skipped",
]
);Structs§
- Note
- Something skipped, and on which line.
- Parsed
- DDL read into the model: a schema of tables, and what was skipped.
- SqlError
- Why DDL could not be read, and on which line.
Constants§
- MAX_
COLUMNS - The most columns (and table constraints) in one table, and the most columns one key names.
- MAX_
INPUT - The most bytes of DDL read.
- MAX_
NESTING - The deepest parentheses nest.
- MAX_
NOTES - The most notes kept; past this they are counted in a last one.
- MAX_
STATEMENTS - The most statements read.
- MAX_
TOKENS - The most tokens (words, names, values, punctuation) in one statement.
Only a
CREATE TABLEstatement’s are kept, one statement at a time.
Functions§
- parse
- Read DDL. See the module docs.