f75f71bbe4
Wires the stratified WHERE-expression fragment into the three
filter commands and compiles the resulting Expr to SQL.
Grammar (data.rs): the `update` / `delete` `where` clause is
now the expression fragment (`Subgrammar(&expr::OR_EXPR)`) in
place of the single `col = val` slot; `show data` gains an
optional `where <expr>` and an optional `limit <n>` (a
non-negative integer, validated at parse time). The
expression's right-hand operands are a schema-aware
`DynamicSubgrammar` so the hint panel still narrows to the
left column's type (ADR-0026 §8) — but the inner grammar is
permissive: a type-mismatched literal still parses (§7).
AST: `RowFilter::Where{column,value}` -> `RowFilter::Where(Expr)`;
`ShowData` gains `filter: Option<Expr>` and `limit: Option<u64>`.
A `RowFilter::eq` convenience constructor keeps simple-equality
call sites and tests readable.
SQL (db.rs): `compile_expr` lowers an `Expr` to a
parameterised WHERE — every literal a `?` placeholder,
identifiers `quote_ident`-quoted, `<>` for inequality. A
literal compared against a column binds through that column's
type where compatible and falls back to its syntactic shape on
a mismatch (§7 — permissive). `show data ... limit n` emits
`LIMIT ?` with an implicit primary-key `ORDER BY`, so it is a
stable "first n by primary key".
completion.rs: `invalid_ident_at_cursor` no longer mis-flags a
digit-led literal (`1`) as an unknown column now that the
WHERE operand slot also accepts a column reference; a
`ProseOnly` slot suppresses keyword candidates even when the
expected set also carries a column ident.
11 db integration tests cover AND / OR / NOT, BETWEEN, IN,
LIKE, filtered `show data`, and limit ordering; walker and
expr unit tests cover the parse surface. Type-mismatch /
`= NULL` diagnostic flagging (§7 highlight + hint) is the
remaining ADR-0026 piece.
57 lines
1.8 KiB
Rust
57 lines
1.8 KiB
Rust
//! The Playground DSL.
|
|
//!
|
|
//! The DSL is the simplified, beginner-friendly command surface
|
|
//! described in ADR-0003. This module owns its grammar
|
|
//! (`parser`), its abstract syntax tree (`command`), and the
|
|
//! user-facing type vocabulary (`types`).
|
|
//!
|
|
//! Raw SQL handling for advanced mode is intentionally *not* in
|
|
//! this module — that path uses `sqlparser-rs` and lives
|
|
//! elsewhere when it lands.
|
|
|
|
pub mod action;
|
|
pub mod command;
|
|
pub mod grammar;
|
|
pub mod parser;
|
|
pub mod shortid;
|
|
pub mod types;
|
|
pub mod value;
|
|
pub mod walker;
|
|
|
|
pub use action::ReferentialAction;
|
|
pub use command::{
|
|
AppCommand, ChangeColumnMode, ColumnSpec, Command, CompareOp, Expr, IndexSelector,
|
|
MessagesValue, ModeValue, Operand, Predicate, RelationshipSelector, RowFilter,
|
|
};
|
|
pub use parser::{ParseError, parse_command};
|
|
pub use types::Type;
|
|
pub use value::Value;
|
|
|
|
/// Prefix every echoed DSL command carries in the output
|
|
/// panel — i.e. `[simple] running: <input>` reads as
|
|
/// `[simple]` (tag) + `running: ` (this constant) + the
|
|
/// user's input.
|
|
///
|
|
/// The catalog template `dsl.running` is contracted to equal
|
|
/// `format!("{ECHO_PREFIX}{{input}}")`. The constant lives
|
|
/// in code because the echo-line renderer (ADR-0022 §5)
|
|
/// peels this prefix off and re-tokenises the rest for
|
|
/// highlighting; a unit test (`echo_prefix_matches_catalog_template`)
|
|
/// pins the binding.
|
|
pub const ECHO_PREFIX: &str = "running: ";
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::ECHO_PREFIX;
|
|
|
|
#[test]
|
|
fn echo_prefix_matches_catalog_template() {
|
|
// The catalog template `dsl.running` must produce
|
|
// `<ECHO_PREFIX><input>` so the echo-line renderer can
|
|
// peel the prefix and re-tokenise the rest. A
|
|
// translator changing the prefix breaks this test.
|
|
let rendered = crate::t!("dsl.running", input = "");
|
|
assert_eq!(rendered, ECHO_PREFIX);
|
|
}
|
|
}
|