diff --git a/Cargo.toml b/Cargo.toml index 895f07f6a..430d2d3dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,9 +18,15 @@ edition = "2018" name = "sqlparser" path = "src/lib.rs" +[features] +cst = ["rowan"] # Retain a concrete synatax tree, available as `parser.syntax()` + [dependencies] -bigdecimal = { version = "0.1.0", optional = true } +bigdecimal = { version = "0.1.0", optional = true, features = ["serde"] } log = "0.4.5" +rowan = { version = "0.10.0", optional = true, features = ["serde1"] } +serde = { version = "1.0.106", features = ["derive"] } +serde_json = "1.0.52" [dev-dependencies] simple_logger = "1.0.1" diff --git a/README.md b/README.md index 24674d911..170a31dee 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,187 @@ -# Extensible SQL Lexer and Parser for Rust +> _The following pertains to the `cst` branch; the [upstream README is below](#upstream-readme)._ +> +> ⚠️ This branch is regularly rebased. Please let me know before working off it to coordinate. + +**Preserving full source code information ([#161](https://github.com/andygrove/sqlparser-rs/issues/161)) would enable SQL rewriting/refactoring tools based on sqlparser-rs.** For example: +1. **Error reporting**, both in the parser and in later stages of query processing, would benefit from knowing the source code location of SQL constructs ([#179](https://github.com/andygrove/sqlparser-rs/issues/179)) +2. **SQL pretty-printing** requires comments to be preserved in AST (see [#175](https://github.com/andygrove/sqlparser-rs/issues/175), mentioning [forma](https://github.com/maxcountryman/forma)) +3. **Refactoring via AST transformations** would also benefit from having full control over serialization, a possible solution for dialect-specific "writers" ([#18](https://github.com/andygrove/sqlparser-rs/issues/18)) +4. Analyzing partially invalid code may be useful in the context of an IDE or other tooling. + +**I think that adopting [rust-analyzer's design][ra-syntax], that includes a lossless syntax tree, is the right direction for sqlparser-rs.** In addition to solving the use-cases described above, it helps in other ways: + +5. We can omit syntax that does not affect semantics of the query (e.g. [`ROW` vs `ROWS`](https://github.com/andygrove/sqlparser-rs/blob/418b9631ce9c24cf9bb26cf7dd9e42edd29de985/src/ast/query.rs#L416)) from the typed AST by default, reducing the implementation effort. +6. Having a homogenous syntax tree also alleviates the need for a "visitor" ([#114](https://github.com/andygrove/sqlparser-rs/pull/114)), also reducing the burden on implementors of new syntax + +In 2020 many new people contributed to `sqlparser-rs`, some bringing up the use-cases above. I found myself mentioning this design multiple times, so I felt I should "show the code" instead of just talking about it. + +Current typed AST vs rowan +========================== + +To recap, the input SQL is currently parsed directly into _typed AST_ - with each node of the tree represented by a Rust `struct`/`enum` of a specific type, referring to other structs of specific type, such as: + + struct Select { + pub projection: Vec, + ... + } + +We try to retain most of "important" syntax in this representation (including, for example, [`Ident::quote_style`](https://github.com/andygrove/sqlparser-rs/blob/d32df527e68dd76d857f47ea051a3ec22138469b/src/ast/mod.rs#L77) and [`OffsetRows`](https://github.com/andygrove/sqlparser-rs/blob/418b9631ce9c24cf9bb26cf7dd9e42edd29de985/src/ast/query.rs#L416)), but there doesn't seem to be a practical way to extend it to also store whitespace, comments, and source code spans. + +The lossless syntax tree +------------------------ + +In the alternative design, the parser produces a tree (which I'll call "CST", [not 100% correct though it is](https://dev.to/cad97/lossless-syntax-trees-280c)), in which every node has has the same Rust type (`SyntaxNode`), and a numeric `SyntaxKind` determines what kind of node it is. Under the hood, the leaf and the non-leaf nodes are different: + +* Each leaf node stores a slice of the source text; +* Each intermediate node represents a string obtained by concatenatenating the text of its children; +* The root node, consequently, represents exactly the original source code. + +_(The actual [rust-analyzer's design][ra-syntax] is more involved, but the details are not relevant to this discussion.)_ + +As an example, an SQL query "`select DISTINCT /* ? */ 1234`" could be represented as a tree like the following one: + + SELECT@0..29 + Keyword@0..6 "select" + Whitespace@6..7 " " + DISTINCT_OR_ALL + Keyword@7..15 "DISTINCT" + SELECT_ITEM_UNNAMED@16..29 + Whitespace@16..17 " " + Comment@17..24 "/* ? */" + Whitespace@24..25 " " + Number@25..29 "1234" + +_(Using the `SyntaxKind@start_pos..end_pos "relevant source code"` notation)_ + +Note how all the formatting and comments are retained. + +Such tree data structure is available for re-use as a separate crate ([`rowan`](https://github.com/rust-analyzer/rowan)), and **as the proof-of-concept I extended the parser to populate a rowan-based tree _along with the typed AST_, for a few of the supported SQL constructs.** + +Open question: The future design of the typed AST +------------------------------------------------- + +Though included in the PoC, **constructing both an AST and a CST in parallel should be considered a transitional solution only**, as it will not let us reap the full benefits of the proposed design (esp. points 1, 4, and 5). Additionally, the current one-AST-fits-all approach makes every new feature in the parser a (semver) breaking change, and makes the types as loose as necessary to fit the common denominator (e.g. if something is optional in one dialect, it has to be optional in the AST). + +What can we do instead? + +### Rust-analyzer's AST + +In rust-analyzer the AST layer does not store any additional data. Instead a "newtype" (a struct with exactly one field - the underlying CST node) is defined for each AST node type: + + struct Select { syntax: SyntaxNode }; // the newtype + impl Select { + fn syntax(&self) -> &SyntaxNode { &self.syntax } + fn cast(syntax: SyntaxNode) -> Option { + match syntax.kind { + SyntaxKind::SELECT => Some(Select { syntax }), + _ => None, + } + } + ... + +Such newtypes define APIs to let the user navigate the AST through accessors specific to this node type: + + // ...`impl Select` continued + pub fn distinct_or_all(&self) -> Option { + AstChildren::new(&self.syntax).next() + } + pub fn projection(&self) -> AstChildren { + AstChildren::new(&self.syntax) + } + +These accessors go through the node's direct childen, looking for nodes of a specific `SyntaxKind` (by trying to `cast()` them to the requested output type). + +This approach is a good fit for IDEs, as it can work on partial / invalid source code due to its lazy nature. Whether it is acceptable in other contexts is an open question ([though it was **not** rejected w.r.t rust-analyzer and rustc sharing a libsyntax2.0](https://github.com/rust-lang/rfcs/pull/2256)). + +### Code generation and other options for the AST + +Though the specific form of the AST is yet to be determined, it seems necessary to use some form of automation to build an AST based on a CST, so that we don't have 3 places (the parser, the AST, and the CST->AST converter) to keep synchronised. + +Rust-analyzer implements its own simple code generator, which would [generate](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/xtask/src/codegen/gen_syntax.rs#L47) methods like the above based on a definition [like](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/xtask/src/ast_src.rs#L293) this: + + const AST_SRC: AstSrc = AstSrc { + nodes: &ast_nodes! { + struct Select { + DistinctOrAll, + projection: [SelectItem], + ... + +_(Here the `ast_nodes!` macro converts something that looks like a simplified `struct` declaration to a literal value describing the struct's name and fields.)_ + +A similar approach could be tried to eagerly build an AST akin to our current one [[*](#ref-1)]. A quick survey of our AST reveals some incompatibilities between the rust-analyzer-style codegen and our use-case: + +* In rust-analyzer all AST enums use fieldless variants (`enum Foo { Bar(Bar), Baz(Baz) }`), making codegen easier. sqlparser uses variants with fields, though there was a request to move to fieldless ([#40](https://github.com/andygrove/sqlparser-rs/issues/40)). + + In my view, our motivation here was conciseness and inertia (little reason to rewrite, and much effort needed to update - both the library, including the tests, and the consumers). I think this can change. + +* RA's codegen assumes that the _type_ of a node usually determines its relation to its parent: different fields in a code-generated struct have to be of different types, as all children of a given type are available from a single "field". Odd cases like `BinExpr`'s `lhs` and `rhs` (both having the type `Expr`) are [implemented manually](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/src/ast/expr_extensions.rs#L195). + + It's clear this does not work as well for an AST like ours. In rare cases there's a clear problem with our AST (e.g. `WhenClause` for `CASE` expressions is introduced on this branch), but consider: + + pub struct Select { + //... + pub projection: Vec, + pub where: Option, + pub group_by: Vec, + pub having: Option, + + The CST for this should probably have separate branches for `WHERE`, `GROUP BY` and `HAVING` at least. Should we introduce additional types like `Where` or make codegen handle this somehow? + +* Large portions of the `struct`s in our AST are allocated at once. We use `Box` only where necessary to break the cycles. RA's codegen doesn't have a way to specify these points. + +Of course we're not limited to stealing ideas from rust-analyzer, so alternatives can be considered. + +* Should we code-gen based on a real AST definition instead of a quasi-Rust code inside a macro like `ast_nodes`? +* Can `serde` be of help? + +I think the design of the CST should be informed by the needs of the AST, so **this is the key question for me.** I've extracted the types and the fields of the current AST into a table (see `ast-stats.js` and `ast-fields.tsv` in `util/`) to help come up with a solution. + + +Other tasks +----------- + +Other than coming up with AST/CST design, there are a number of things to do: + +* Upstream the "Support parser backtracking in the GreenNodeBuilder" commit to avoid importing a copy of `GreenNodeBuilder` into sqlparser-rs +* Setting up the testing infrastructure for the CST (rust-analyzer, again, has some good ideas here) + + +- Fix `Token`/`SyntaxKind` duplication, changing the former to + store a slice of the original source code, e.g. + `(SyntaxKind, SmolStr)` + + This should also fix the currently disabled test-cases where `Token`'s + `to_string()` does not return the original string: + + * `parse_escaped_single_quote_string_predicate` + * `parse_literal_string` (the case of `HexLiteralString`) + +- Fix the hack in `parse_keyword()` to remap the token type (RA has + `bump_remap() for this) + +- Fix the `Parser::pending` hack (needs rethinking parser's API) + + Probably related is the issue of handling whitespace and comments: + the way this prototype handles it looks wrong. + +Remarks +------- + +1. [*] During such eager construction of an AST we could also bail on CST nodes that have no place in the typed AST. This seems a part of the possible solution to the dialect problem: this way the parser can recognize a dialect-specific construct, while each consumer can pick which bits they want to support by defining their own typed AST. + + +[ra-syntax]: https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/dev/syntax.md + + + + + + + + + +# Upstream README [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Version](https://img.shields.io/crates/v/sqlparser.svg)](https://crates.io/crates/sqlparser) diff --git a/examples/cli.rs b/examples/cli.rs index 2b0822584..936e0e132 100644 --- a/examples/cli.rs +++ b/examples/cli.rs @@ -17,7 +17,7 @@ use std::fs; use sqlparser::dialect::*; -use sqlparser::parser::Parser; +use sqlparser::{parser::Parser, tokenizer::Tokenizer}; fn main() { simple_logger::init().unwrap(); @@ -45,19 +45,40 @@ fn main() { chars.next(); chars.as_str() }; - let parse_result = Parser::parse_sql(&*dialect, without_bom); + + let tokens = Tokenizer::new(&*dialect, without_bom) + .tokenize() + .unwrap_or_else(|e| { + println!("Error tokenizing: {:?}", e); + std::process::exit(1); + }); + + let mut parser = Parser::new(tokens); + let parse_result = parser.parse_statements(); + match parse_result { Ok(statements) => { - println!( - "Round-trip:\n'{}'", - statements - .iter() - .map(std::string::ToString::to_string) - .collect::>() - .join("\n") - ); - println!("Parse results:\n{:#?}", statements); - std::process::exit(0); + if cfg!(not(feature = "cst")) { + println!( + "Round-trip:\n'{}'", + statements + .iter() + .map(std::string::ToString::to_string) + .collect::>() + .join("\n") + ); + println!("Parse results:\n{:#?}", statements); + } else { + #[cfg(feature = "cst")] + { + let syn = parser.syntax(); + println!("Parse tree:\n{:#?}", syn); + let serialized = serde_json::to_string(&syn).unwrap(); + println!("Parse tree as json:\n{}", serialized); + let serialized = serde_json::to_string(&statements).unwrap(); + println!("AST as JSON:\n{}", serialized); + } + } } Err(e) => { println!("Error during parsing: {:?}", e); diff --git a/src/ast/data_type.rs b/src/ast/data_type.rs index cfbc2147d..d7911546f 100644 --- a/src/ast/data_type.rs +++ b/src/ast/data_type.rs @@ -11,10 +11,11 @@ // limitations under the License. use super::ObjectName; +use serde::{Deserialize, Serialize}; use std::fmt; /// SQL data types -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum DataType { /// Fixed-length character type e.g. CHAR(10) Char(Option), diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 776927669..b9febffec 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -13,10 +13,11 @@ //! AST types specific to CREATE/ALTER variants of [Statement] //! (commonly referred to as Data Definition Language, or DDL) use super::{display_comma_separated, DataType, Expr, Ident, ObjectName}; +use serde::{Deserialize, Serialize}; use std::fmt; /// An `ALTER TABLE` (`Statement::AlterTable`) operation -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum AlterTableOperation { /// `ADD ` AddConstraint(TableConstraint), @@ -35,7 +36,7 @@ impl fmt::Display for AlterTableOperation { /// A table-level constraint, specified in a `CREATE TABLE` or an /// `ALTER TABLE ADD ` statement. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum TableConstraint { /// `[ CONSTRAINT ] { PRIMARY KEY | UNIQUE } ()` Unique { @@ -94,7 +95,7 @@ impl fmt::Display for TableConstraint { } /// SQL column definition -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ColumnDef { pub name: Ident, pub data_type: DataType, @@ -128,7 +129,7 @@ impl fmt::Display for ColumnDef { /// For maximum flexibility, we don't distinguish between constraint and /// non-constraint options, lumping them all together under the umbrella of /// "column options," and we allow any column option to be named. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ColumnOptionDef { pub name: Option, pub option: ColumnOption, @@ -142,7 +143,7 @@ impl fmt::Display for ColumnOptionDef { /// `ColumnOption`s are modifiers that follow a column definition in a `CREATE /// TABLE` statement. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ColumnOption { /// `NULL` Null, @@ -219,7 +220,7 @@ fn display_constraint_name<'a>(name: &'a Option) -> impl fmt::Display + ' /// { RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT }` /// /// Used in foreign key constraints in `ON UPDATE` and `ON DELETE` options. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ReferentialAction { Restrict, Cascade, diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 2dbf42b29..aa531d5f8 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -18,6 +18,7 @@ mod operator; mod query; mod value; +use serde::{Deserialize, Serialize}; use std::fmt; pub use self::data_type::DataType; @@ -70,7 +71,7 @@ where } /// An identifier, decomposed into its value or character data and the quote style. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Ident { /// The value of the identifier without quotes. pub value: String, @@ -126,7 +127,7 @@ impl fmt::Display for Ident { } /// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ObjectName(pub Vec); impl fmt::Display for ObjectName { @@ -140,7 +141,7 @@ impl fmt::Display for ObjectName { /// The parser does not distinguish between expressions of different types /// (e.g. boolean vs string), so the caller must handle expressions of /// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Expr { /// Identifier e.g. table name or column name Identifier(Ident), @@ -207,15 +208,10 @@ pub enum Expr { Value(Value), /// Scalar function call e.g. `LEFT(foo, 5)` Function(Function), - /// `CASE [] WHEN THEN ... [ELSE ] END` - /// - /// Note we only recognize a complete single expression as ``, - /// not `< 0` nor `1, 2, 3` as allowed in a `` per - /// + /// `CASE [] [ELSE ] END` Case { operand: Option>, - conditions: Vec, - results: Vec, + when_clauses: Vec, else_result: Option>, }, /// An exists expression `EXISTS(SELECT ...)`, used in expressions like @@ -282,17 +278,14 @@ impl fmt::Display for Expr { Expr::Function(fun) => write!(f, "{}", fun), Expr::Case { operand, - conditions, - results, + when_clauses, else_result, } => { f.write_str("CASE")?; if let Some(operand) = operand { write!(f, " {}", operand)?; } - for (c, r) in conditions.iter().zip(results) { - write!(f, " WHEN {} THEN {}", c, r)?; - } + write!(f, " {}", display_separated(when_clauses, " "))?; if let Some(else_result) = else_result { write!(f, " ELSE {}", else_result)?; @@ -306,8 +299,25 @@ impl fmt::Display for Expr { } } +/// An individual `WHEN THEN ` clause from a `CASE`. +/// +/// Note: we only recognize a complete single expression as ``, +/// not `< 0` nor `1, 2, 3` as allowed in a `` per +/// +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct WhenClause { + pub condition: Expr, + pub result: Expr, +} + +impl fmt::Display for WhenClause { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "WHEN {} THEN {}", self.condition, self.result) + } +} + /// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct WindowSpec { pub partition_by: Vec, pub order_by: Vec, @@ -352,7 +362,7 @@ impl fmt::Display for WindowSpec { /// /// Note: The parser does not validate the specified bounds; the caller should /// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct WindowFrame { pub units: WindowFrameUnits, pub start_bound: WindowFrameBound, @@ -363,7 +373,7 @@ pub struct WindowFrame { // TBD: EXCLUDE } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum WindowFrameUnits { Rows, Range, @@ -397,7 +407,7 @@ impl FromStr for WindowFrameUnits { } /// Specifies [WindowFrame]'s `start_bound` and `end_bound` -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum WindowFrameBound { /// `CURRENT ROW` CurrentRow, @@ -421,7 +431,7 @@ impl fmt::Display for WindowFrameBound { /// A top-level statement (SELECT, INSERT, CREATE, etc.) #[allow(clippy::large_enum_variant)] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Statement { /// SELECT Query(Box), @@ -765,7 +775,7 @@ impl fmt::Display for Statement { } /// SQL assignment `foo = expr` as used in SQLUpdate -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Assignment { pub id: Ident, pub value: Expr, @@ -778,7 +788,7 @@ impl fmt::Display for Assignment { } /// A function call -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Function { pub name: ObjectName, pub args: Vec, @@ -804,7 +814,7 @@ impl fmt::Display for Function { } /// External table's available file format -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum FileFormat { TEXTFILE, SEQUENCEFILE, @@ -855,7 +865,7 @@ impl FromStr for FileFormat { /// A `LISTAGG` invocation `LISTAGG( [ DISTINCT ] [, ] [ON OVERFLOW ] ) ) /// [ WITHIN GROUP (ORDER BY [, ...] ) ]` -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ListAgg { pub distinct: bool, pub expr: Box, @@ -891,7 +901,7 @@ impl fmt::Display for ListAgg { } /// The `ON OVERFLOW` clause of a LISTAGG invocation -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ListAggOnOverflow { /// `ON OVERFLOW ERROR` Error, @@ -924,7 +934,7 @@ impl fmt::Display for ListAggOnOverflow { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ObjectType { Table, View, @@ -943,7 +953,7 @@ impl fmt::Display for ObjectType { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct SqlOption { pub name: Ident, pub value: Value, @@ -955,7 +965,7 @@ impl fmt::Display for SqlOption { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum TransactionMode { AccessMode(TransactionAccessMode), IsolationLevel(TransactionIsolationLevel), @@ -971,7 +981,7 @@ impl fmt::Display for TransactionMode { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum TransactionAccessMode { ReadOnly, ReadWrite, @@ -987,7 +997,7 @@ impl fmt::Display for TransactionAccessMode { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum TransactionIsolationLevel { ReadUncommitted, ReadCommitted, @@ -1007,7 +1017,7 @@ impl fmt::Display for TransactionIsolationLevel { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ShowStatementFilter { Like(String), Where(Expr), @@ -1023,7 +1033,7 @@ impl fmt::Display for ShowStatementFilter { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum SetVariableValue { Ident(Ident), Literal(Value), diff --git a/src/ast/operator.rs b/src/ast/operator.rs index c9f5eb2e9..b112b080c 100644 --- a/src/ast/operator.rs +++ b/src/ast/operator.rs @@ -10,10 +10,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +use serde::{Deserialize, Serialize}; use std::fmt; /// Unary operators -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum UnaryOperator { Plus, Minus, @@ -31,7 +32,7 @@ impl fmt::Display for UnaryOperator { } /// Binary operators -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum BinaryOperator { Plus, Minus, diff --git a/src/ast/query.rs b/src/ast/query.rs index a5918f1a3..239ace7de 100644 --- a/src/ast/query.rs +++ b/src/ast/query.rs @@ -14,7 +14,7 @@ use super::*; /// The most complete variant of a `SELECT` query expression, optionally /// including `WITH`, `UNION` / other set operations, and `ORDER BY`. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Query { /// WITH (common table expressions, or CTEs) pub ctes: Vec, @@ -54,7 +54,7 @@ impl fmt::Display for Query { /// A node in a tree, representing a "query body" expression, roughly: /// `SELECT ... [ {UNION|EXCEPT|INTERSECT} SELECT ...]` -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum SetExpr { /// Restricted SELECT .. FROM .. HAVING (no ORDER BY or set operations) Select(Box +SetExpr::Query SetExpr Query unnamed Box +SetExpr::SetOperation SetExpr SetOperation op SetOperator +SetExpr::SetOperation SetExpr SetOperation all bool +SetExpr::SetOperation SetExpr SetOperation left Box +SetExpr::SetOperation SetExpr SetOperation right Box +SetExpr::Values SetExpr Values unnamed Values +SelectItem::UnnamedExpr SelectItem UnnamedExpr unnamed Expr +SelectItem::ExprWithAlias SelectItem ExprWithAlias expr Expr +SelectItem::ExprWithAlias SelectItem ExprWithAlias alias Ident +SelectItem::QualifiedWildcard SelectItem QualifiedWildcard unnamed ObjectName +TableFactor::Table TableFactor Table name ObjectName +TableFactor::Table TableFactor Table alias Option +TableFactor::Table TableFactor Table args Vec +TableFactor::Table TableFactor Table with_hints Vec +TableFactor::Derived TableFactor Derived lateral bool +TableFactor::Derived TableFactor Derived subquery Box +TableFactor::Derived TableFactor Derived alias Option +TableFactor::NestedJoin TableFactor NestedJoin unnamed Box +JoinOperator::Inner JoinOperator Inner unnamed JoinConstraint +JoinOperator::LeftOuter JoinOperator LeftOuter unnamed JoinConstraint +JoinOperator::RightOuter JoinOperator RightOuter unnamed JoinConstraint +JoinOperator::FullOuter JoinOperator FullOuter unnamed JoinConstraint +JoinConstraint::On JoinConstraint On unnamed Expr +JoinConstraint::Using JoinConstraint Using unnamed Vec +Value::Number Value Number unnamed String +Value::Number Value Number unnamed BigDecimal +Value::SingleQuotedString Value SingleQuotedString unnamed String +Value::NationalStringLiteral Value NationalStringLiteral unnamed String +Value::HexStringLiteral Value HexStringLiteral unnamed String +Value::Boolean Value Boolean unnamed bool +Value::Date Value Date unnamed String +Value::Time Value Time unnamed String +Value::Timestamp Value Timestamp unnamed String +Value::Interval Value Interval value String +Value::Interval Value Interval leading_field DateTimeField +Value::Interval Value Interval leading_precision Option +Value::Interval Value Interval last_field Option +Value::Interval Value Interval fractional_seconds_precision Option diff --git a/util/ast-stats.js b/util/ast-stats.js new file mode 100644 index 000000000..b293ae4a7 --- /dev/null +++ b/util/ast-stats.js @@ -0,0 +1,103 @@ +// Getting this out of the source code is currently a manual process: +// 1) Run `egrep -hv "//!" src/ast/*.rs > mods` +// this is required, because astexplorer's parser doesn't like the `//!` parent doc-comments +// 2) Paste the results into https://astexplorer.net/ (select the Rust mode) +// 3) Copy the AST data back to `const json =` +// 4) Copy the source code to `srcText`, escaping backslashes (`\` -> `\\`) and backticks ` -> \` +// 5) Run: node util/ast-stats.js > util/ast-fields.tsv + +const {srcText, json} = require("./real-data.js"); +// const {srcText, json} = require("./test-data.js"); + +/** Walk the JSON object representing the AST depth-first, calling `visitor` on each "complex" node. */ +function walk(ast, path, visitor) { + ast.path = path; + + if (!visitor(ast)) return; + const nodeName = (ast instanceof Array ? "Array" : ast["_type"]); + // console.log(`@${path}: ${nodeName} ${ast.toString().substring(1,20)}`) + for (var prop in ast) { + if (ast[prop] instanceof Object) { + walk(ast[prop], (path ? path + "/" : "") + nodeName, visitor); + } + } +} + +/** Return all AST objects matching the predicate in an array. + Note: for nested objects only the top-most one is included in the results */ +function find(ast, filterFn) { + let rv = []; + walk(ast, "", node => { + if (filterFn(node)) { + rv.push(node); + return false; + } + return true; + }); + return rv; +} + +/** Return string in the given span of the text. + * A span is an `{start: LC, end: LC}` object, where + * LC is {line, column} sub-objects with 1-based positions, inclusive. + */ +function src(text, span) { + const lineLengths = text.split("\n").map(line => line.length); + function pos2idx(pos) { + let idx = 0; + for (let i = 0; i < pos.line-1; ++i) { + idx += lineLengths[i] + 1; + } + idx += pos.column; + //console.log(`pos2idx(${pos.line}, ${pos.column}) = ${idx}`) + return idx; + } + return text.substring(pos2idx(span.start), pos2idx(span.end)) +} + +// let spans = find(json, (node) => node._type == "Field").map(node => node.span); +// console.log(src(srcText, spans[0])); + +/** A predicate to filter declarations preceded by a set of #[derive]s used for AST structs/enums */ +function filterAST(structOrEnum) { + const attrs = structOrEnum.attrs.map(attr => src(srcText, attr.span)); + const isAST = attrs.some(a => a == "#[derive(Debug, Clone, PartialEq, Eq, Hash)]"); + //console.log(structOrEnum.ident.to_string, isAST, isAST ? "" : attrs) + return isAST; +} + + +const structs = find(json, n => n._type == "ItemStruct").filter(filterAST); +const enums = find(json, n => n._type == "ItemEnum").filter(filterAST); + +const enumVariants = enums.flatMap(enum_ => { + const enum_name = enum_.ident.to_string; + return find(enum_, n => n._type == "Variant").map(variant => ({ + struct_name: `${enum_name}::${variant.ident.to_string}`, + enum_name: enum_name, + variant_name: variant.ident.to_string, + node: variant + })); +}); + +const structsAndEnumVariants = structs.map(struct => ({ + struct_name: struct.ident.to_string, + enum_name: "", variant_name: "", + node: struct +})).concat(enumVariants); + +let fields = structsAndEnumVariants.flatMap(item => { + return find(item, (n) => n._type == "Field").map(field => ({ + struct_name: item.struct_name, + enum_name: item.enum_name, variant_name: item.variant_name, + field_name: field.ident ? field.ident.to_string : "unnamed", // e.g. (Bar, Baz) + field_type: src(srcText, field.ty.span) + })); +}); + +const FIELDS = ["struct_name", "enum_name", "variant_name", "field_name", "field_type"]; +console.log(FIELDS.join("\t")); +console.log(fields.map(row => FIELDS.map(col => row[col]).join("\t")).join("\n")); +// console.log(fields); + +//console.log(src(srcText, {start:{line:1135, column:12}, end: {line:1135, column:17}})); diff --git a/util/test-data.js b/util/test-data.js new file mode 100644 index 000000000..8d8a8e9f5 --- /dev/null +++ b/util/test-data.js @@ -0,0 +1,3068 @@ +const srcText = `#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Query { + /// WITH (common table expressions, or CTEs) + pub ctes: Vec, + /// SELECT or UNION / EXCEPT / INTECEPT + pub body: SetExpr, + /// ORDER BY + pub order_by: Vec, + /// \`LIMIT { | ALL }\` + pub limit: Option, + /// \`OFFSET [ {ROW | ROWS} ]\` + pub offset: Option, + /// \`FETCH {FIRST | NEXT} [ PERCENT ] {ROW | ROWS} | {ONLY | WITH TIES }\` + pub fetch: Option, +}` + +const json = { + "_type": "File", + "attrs": [], + "items": [ + { + "_type": "ItemStruct", + "attrs": [ + { + "_type": "Attribute", + "pound_token": { + "_type": "Pound", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 0 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 1 + } + } + }, + "style": { + "_type": "AttrStyle::Outer" + }, + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "derive", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 2 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 8 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 2 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 8 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 2 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 8 + } + } + }, + "tts": { + "0": { + "_type": "Group", + "delimiter": { + "_type": "Delimiter::Parenthesis" + }, + "stream": { + "0": { + "_type": "Ident", + "to_string": "Debug", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 9 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 14 + } + } + }, + "1": { + "_type": "Punct", + "as_char": ",", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 15 + } + } + }, + "2": { + "_type": "Ident", + "to_string": "Clone", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 16 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 21 + } + } + }, + "3": { + "_type": "Punct", + "as_char": ",", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 22 + } + } + }, + "4": { + "_type": "Ident", + "to_string": "PartialEq", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 23 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 32 + } + } + }, + "5": { + "_type": "Punct", + "as_char": ",", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 32 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 33 + } + } + }, + "6": { + "_type": "Ident", + "to_string": "Eq", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 34 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 36 + } + } + }, + "7": { + "_type": "Punct", + "as_char": ",", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 36 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 37 + } + } + }, + "8": { + "_type": "Ident", + "to_string": "Hash", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 38 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 42 + } + } + }, + "9": { + "_type": "Punct", + "as_char": ",", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 42 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 43 + } + } + }, + "10": { + "_type": "Ident", + "to_string": "Serialize", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 44 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 53 + } + } + }, + "11": { + "_type": "Punct", + "as_char": ",", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 53 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 54 + } + } + }, + "12": { + "_type": "Ident", + "to_string": "Deserialize", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 55 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 66 + } + } + }, + "_type": "TokenStream", + "length": 13 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 8 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 67 + } + } + }, + "_type": "TokenStream", + "length": 1 + }, + "bracket_token": { + "_type": "Bracket", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 1 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 68 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 0 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 68 + } + } + } + ], + "vis": { + "_type": "VisPublic", + "pub_token": { + "_type": "Pub", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 2, + "column": 0 + }, + "end": { + "_type": "LineColumn", + "line": 2, + "column": 3 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 2, + "column": 0 + }, + "end": { + "_type": "LineColumn", + "line": 2, + "column": 3 + } + } + }, + "struct_token": { + "_type": "Struct", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 2, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 2, + "column": 10 + } + } + }, + "ident": { + "_type": "Ident", + "to_string": "Query", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 2, + "column": 11 + }, + "end": { + "_type": "LineColumn", + "line": 2, + "column": 16 + } + } + }, + "generics": { + "_type": "Generics", + "params": { + "_type": "Punctuated", + "length": 0 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 0 + }, + "end": { + "_type": "LineColumn", + "line": 1, + "column": 0 + } + } + }, + "fields": { + "_type": "FieldsNamed", + "named": { + "0": { + "_type": "Field", + "attrs": [ + { + "_type": "Attribute", + "pound_token": { + "_type": "Pound", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 3, + "column": 48 + } + } + }, + "style": { + "_type": "AttrStyle::Outer" + }, + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "doc", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 3, + "column": 48 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 3, + "column": 48 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 3, + "column": 48 + } + } + }, + "tts": { + "0": { + "_type": "Punct", + "as_char": "=", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 3, + "column": 48 + } + } + }, + "1": { + "_type": "Literal", + "to_string": "\" WITH (common table expressions, or CTEs)\"", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 3, + "column": 48 + } + } + }, + "_type": "TokenStream", + "length": 2 + }, + "bracket_token": { + "_type": "Bracket", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 3, + "column": 48 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 3, + "column": 48 + } + } + } + ], + "vis": { + "_type": "VisPublic", + "pub_token": { + "_type": "Pub", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 7 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 7 + } + } + }, + "ident": { + "_type": "Ident", + "to_string": "ctes", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 8 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 12 + } + } + }, + "colon_token": { + "_type": "Colon", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 12 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 13 + } + } + }, + "ty": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Vec", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 17 + } + } + }, + "arguments": { + "_type": "AngleBracketedGenericArguments", + "lt_token": { + "_type": "Lt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 17 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 18 + } + } + }, + "args": { + "0": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Cte", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 18 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 21 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 18 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 21 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 18 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 21 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 18 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 21 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "gt_token": { + "_type": "Gt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 22 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 17 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 22 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 22 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 22 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 22 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 3, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 22 + } + } + }, + "1": { + "_type": "Comma", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 4, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 4, + "column": 23 + } + } + }, + "2": { + "_type": "Field", + "attrs": [ + { + "_type": "Attribute", + "pound_token": { + "_type": "Pound", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 5, + "column": 43 + } + } + }, + "style": { + "_type": "AttrStyle::Outer" + }, + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "doc", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 5, + "column": 43 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 5, + "column": 43 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 5, + "column": 43 + } + } + }, + "tts": { + "0": { + "_type": "Punct", + "as_char": "=", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 5, + "column": 43 + } + } + }, + "1": { + "_type": "Literal", + "to_string": "\" SELECT or UNION / EXCEPT / INTECEPT\"", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 5, + "column": 43 + } + } + }, + "_type": "TokenStream", + "length": 2 + }, + "bracket_token": { + "_type": "Bracket", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 5, + "column": 43 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 5, + "column": 43 + } + } + } + ], + "vis": { + "_type": "VisPublic", + "pub_token": { + "_type": "Pub", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 7 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 7 + } + } + }, + "ident": { + "_type": "Ident", + "to_string": "body", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 8 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 12 + } + } + }, + "colon_token": { + "_type": "Colon", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 12 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 13 + } + } + }, + "ty": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "SetExpr", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 21 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 21 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 21 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 21 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 5, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 21 + } + } + }, + "3": { + "_type": "Comma", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 6, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 6, + "column": 22 + } + } + }, + "4": { + "_type": "Field", + "attrs": [ + { + "_type": "Attribute", + "pound_token": { + "_type": "Pound", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 7, + "column": 16 + } + } + }, + "style": { + "_type": "AttrStyle::Outer" + }, + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "doc", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 7, + "column": 16 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 7, + "column": 16 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 7, + "column": 16 + } + } + }, + "tts": { + "0": { + "_type": "Punct", + "as_char": "=", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 7, + "column": 16 + } + } + }, + "1": { + "_type": "Literal", + "to_string": "\" ORDER BY\"", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 7, + "column": 16 + } + } + }, + "_type": "TokenStream", + "length": 2 + }, + "bracket_token": { + "_type": "Bracket", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 7, + "column": 16 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 7, + "column": 16 + } + } + } + ], + "vis": { + "_type": "VisPublic", + "pub_token": { + "_type": "Pub", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 7 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 7 + } + } + }, + "ident": { + "_type": "Ident", + "to_string": "order_by", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 8 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 16 + } + } + }, + "colon_token": { + "_type": "Colon", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 16 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 17 + } + } + }, + "ty": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Vec", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 18 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 21 + } + } + }, + "arguments": { + "_type": "AngleBracketedGenericArguments", + "lt_token": { + "_type": "Lt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 22 + } + } + }, + "args": { + "0": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "OrderByExpr", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 33 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 33 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 33 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 33 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "gt_token": { + "_type": "Gt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 33 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 34 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 34 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 18 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 34 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 18 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 34 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 18 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 34 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 7, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 34 + } + } + }, + "5": { + "_type": "Comma", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 8, + "column": 34 + }, + "end": { + "_type": "LineColumn", + "line": 8, + "column": 35 + } + } + }, + "6": { + "_type": "Field", + "attrs": [ + { + "_type": "Attribute", + "pound_token": { + "_type": "Pound", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 9, + "column": 29 + } + } + }, + "style": { + "_type": "AttrStyle::Outer" + }, + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "doc", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 9, + "column": 29 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 9, + "column": 29 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 9, + "column": 29 + } + } + }, + "tts": { + "0": { + "_type": "Punct", + "as_char": "=", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 9, + "column": 29 + } + } + }, + "1": { + "_type": "Literal", + "to_string": "\" `LIMIT { | ALL }`\"", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 9, + "column": 29 + } + } + }, + "_type": "TokenStream", + "length": 2 + }, + "bracket_token": { + "_type": "Bracket", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 9, + "column": 29 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 9, + "column": 29 + } + } + } + ], + "vis": { + "_type": "VisPublic", + "pub_token": { + "_type": "Pub", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 7 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 7 + } + } + }, + "ident": { + "_type": "Ident", + "to_string": "limit", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 8 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 13 + } + } + }, + "colon_token": { + "_type": "Colon", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 13 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 14 + } + } + }, + "ty": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Option", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 15 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 21 + } + } + }, + "arguments": { + "_type": "AngleBracketedGenericArguments", + "lt_token": { + "_type": "Lt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 22 + } + } + }, + "args": { + "0": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Expr", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 26 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 26 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 26 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 26 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "gt_token": { + "_type": "Gt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 26 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 27 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 27 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 15 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 27 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 15 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 27 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 15 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 27 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 9, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 27 + } + } + }, + "7": { + "_type": "Comma", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 10, + "column": 27 + }, + "end": { + "_type": "LineColumn", + "line": 10, + "column": 28 + } + } + }, + "8": { + "_type": "Field", + "attrs": [ + { + "_type": "Attribute", + "pound_token": { + "_type": "Pound", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 11, + "column": 39 + } + } + }, + "style": { + "_type": "AttrStyle::Outer" + }, + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "doc", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 11, + "column": 39 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 11, + "column": 39 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 11, + "column": 39 + } + } + }, + "tts": { + "0": { + "_type": "Punct", + "as_char": "=", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 11, + "column": 39 + } + } + }, + "1": { + "_type": "Literal", + "to_string": "\" `OFFSET [ { ROW | ROWS } ]`\"", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 11, + "column": 39 + } + } + }, + "_type": "TokenStream", + "length": 2 + }, + "bracket_token": { + "_type": "Bracket", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 11, + "column": 39 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 11, + "column": 39 + } + } + } + ], + "vis": { + "_type": "VisPublic", + "pub_token": { + "_type": "Pub", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 7 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 7 + } + } + }, + "ident": { + "_type": "Ident", + "to_string": "offset", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 8 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 14 + } + } + }, + "colon_token": { + "_type": "Colon", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 14 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 15 + } + } + }, + "ty": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Option", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 16 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 22 + } + } + }, + "arguments": { + "_type": "AngleBracketedGenericArguments", + "lt_token": { + "_type": "Lt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 23 + } + } + }, + "args": { + "0": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Offset", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 23 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 29 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 23 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 29 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 23 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 29 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 23 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 29 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "gt_token": { + "_type": "Gt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 29 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 30 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 30 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 16 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 30 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 16 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 30 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 16 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 30 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 11, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 30 + } + } + }, + "9": { + "_type": "Comma", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 12, + "column": 30 + }, + "end": { + "_type": "LineColumn", + "line": 12, + "column": 31 + } + } + }, + "10": { + "_type": "Field", + "attrs": [ + { + "_type": "Attribute", + "pound_token": { + "_type": "Pound", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 13, + "column": 86 + } + } + }, + "style": { + "_type": "AttrStyle::Outer" + }, + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "doc", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 13, + "column": 86 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 13, + "column": 86 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 13, + "column": 86 + } + } + }, + "tts": { + "0": { + "_type": "Punct", + "as_char": "=", + "spacing": { + "_type": "Spacing::Alone" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 13, + "column": 86 + } + } + }, + "1": { + "_type": "Literal", + "to_string": "\" `FETCH { FIRST | NEXT } [ PERCENT ] { ROW | ROWS } | { ONLY | WITH TIES }`\"", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 13, + "column": 86 + } + } + }, + "_type": "TokenStream", + "length": 2 + }, + "bracket_token": { + "_type": "Bracket", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 13, + "column": 86 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 13, + "column": 86 + } + } + } + ], + "vis": { + "_type": "VisPublic", + "pub_token": { + "_type": "Pub", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 7 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 7 + } + } + }, + "ident": { + "_type": "Ident", + "to_string": "fetch", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 8 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 13 + } + } + }, + "colon_token": { + "_type": "Colon", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 13 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 14 + } + } + }, + "ty": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Option", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 15 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 21 + } + } + }, + "arguments": { + "_type": "AngleBracketedGenericArguments", + "lt_token": { + "_type": "Lt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 22 + } + } + }, + "args": { + "0": { + "_type": "TypePath", + "path": { + "_type": "Path", + "segments": { + "0": { + "_type": "PathSegment", + "ident": { + "_type": "Ident", + "to_string": "Fetch", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 27 + } + } + }, + "arguments": { + "_type": "PathArguments::None" + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 27 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 27 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 22 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 27 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "gt_token": { + "_type": "Gt", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 27 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 28 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 21 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 28 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 15 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 28 + } + } + }, + "_type": "Punctuated", + "length": 1 + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 15 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 28 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 15 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 28 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 13, + "column": 4 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 28 + } + } + }, + "11": { + "_type": "Comma", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 14, + "column": 28 + }, + "end": { + "_type": "LineColumn", + "line": 14, + "column": 29 + } + } + }, + "_type": "Punctuated", + "length": 12 + }, + "brace_token": { + "_type": "Brace", + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 2, + "column": 17 + }, + "end": { + "_type": "LineColumn", + "line": 15, + "column": 1 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 2, + "column": 17 + }, + "end": { + "_type": "LineColumn", + "line": 15, + "column": 1 + } + } + }, + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 0 + }, + "end": { + "_type": "LineColumn", + "line": 15, + "column": 1 + } + } + } + ], + "span": { + "_type": "Span", + "start": { + "_type": "LineColumn", + "line": 1, + "column": 0 + }, + "end": { + "_type": "LineColumn", + "line": 15, + "column": 1 + } + } +}; + +module.exports = {srcText: srcText, json:json};