diff --git a/crates/definitions/src/data.rs b/crates/definitions/src/data.rs index 8a0dde3..bf81523 100644 --- a/crates/definitions/src/data.rs +++ b/crates/definitions/src/data.rs @@ -68,6 +68,7 @@ pub const TOKENS: Tokens<'_> = Tokens { T!("and"), T!("annotations"), T!("anyschema"), + T!("apply"), T!("array"), T!("as"), T!("asc"), @@ -109,6 +110,7 @@ pub const TOKENS: Tokens<'_> = Tokens { T!("containers_default"), T!("context"), T!("create"), + T!("cross"), T!("crossedition"), T!("cube"), T!("current_user"), @@ -158,6 +160,7 @@ pub const TOKENS: Tokens<'_> = Tokens { T!("foreign"), T!("forward"), T!("from"), + T!("full"), T!("function"), T!("grant"), T!("group"), @@ -172,6 +175,7 @@ pub const TOKENS: Tokens<'_> = Tokens { T!("index"), T!("indicator"), T!("initially"), + T!("inner"), T!("insert"), T!("instead"), T!("int"), @@ -181,10 +185,12 @@ pub const TOKENS: Tokens<'_> = Tokens { T!("invisible"), T!("is"), T!("java"), + T!("join"), T!("key"), T!("language"), T!("large"), T!("last"), + T!("left"), T!("length"), T!("library"), T!("like", "like", "comparison_op"), @@ -200,6 +206,7 @@ pub const TOKENS: Tokens<'_> = Tokens { T!("month"), T!("name"), T!("national"), + T!("natural"), T!("nchar"), T!("nclob"), T!("new"), @@ -229,10 +236,12 @@ pub const TOKENS: Tokens<'_> = Tokens { T!("order"), T!("others"), T!("out"), + T!("outer"), T!("package"), T!("parallel_enable"), T!("parameters"), T!("parent"), + T!("partition"), T!("pipelined"), T!("plpgsql"), T!("pls_integer"), @@ -263,6 +272,7 @@ pub const TOKENS: Tokens<'_> = Tokens { T!("reverse"), T!("revoke"), T!("rollup"), + T!("right"), T!("row"), T!("rowid"), T!("rowtype"), @@ -344,6 +354,8 @@ pub const SYNTAX_NODES: &'_ [SyntaxNode<'_>] = &[ S!("connect_by_root", "The CONNECT_BY_ROOT operator"), S!("connect", "The CONNECT BY clause in selects"), S!("constraint", "A node that marks a full constraint"), + S!("cross_join_clause", "A node that contains a full CROSS JOIN clause"), + S!("cross_outer_apply_clause", "A node that contains a full cross outer apply clause"), S!("cursor_parameter_declaration", "A node containing a cursor parameter declaration"), S!("cursor_parameter_declarations", "A node containing cursor parameter declarations"), S!("cursor_stmt", "A node that marks a full cursor statement"), @@ -366,19 +378,24 @@ pub const SYNTAX_NODES: &'_ [SyntaxNode<'_>] = &[ S!("hierarchical_op", "An operator in hierarchical queries"), S!("ident", "An identifier, either quoted or unquoted"), S!("ident_group", "An identifier group, consisting of multiple idents"), + S!("inner_join_clause", "A node that contains an INNER JOIN clause"), S!("insert_stmt", "A node that marks a full INSERT statement"), S!("integer", "Any integer, positive and negative"), S!("into_clause", "A node that contains an `INTO` clause of a SELECT statement"), + S!("join_clause", "A node that contains a JOIN clause"), S!("keyword", "A SQL keyword, e.g. `CREATE`"), S!("logic_op", "Represents a logical SQL operator (AND, OR, NOT)"), S!("l_paren", "Left Paren"), S!("minus", "A minus `-`"), + S!("natural_join_clause", "A node containing an NATURAL JOIN clause"), S!("not", "Unary logical operator NOT"), S!("or", "Logical operator OR"), S!("order_by_clause", "A node containing a full order by clause"), + S!("outer_join_clause", "A node containing a full OUTER JOIN clause"), S!("package", "A node that marks a full CREATE PACKAGE BODY block"), S!("param", "A single Param node, consisting of name & type"), S!("param_list", "A node that consists of multiple parameters"), + S!("partition_by_clause", "A node that contains a PARTITION BY clause"), S!("percentage", "Percentage symbol"), S!("plus", "A plus `+`"), S!("prior", "The PL/SQL unary prior operator"), diff --git a/crates/source_gen/src/lexer/generated.rs b/crates/source_gen/src/lexer/generated.rs index 78802ec..8cf4656 100644 --- a/crates/source_gen/src/lexer/generated.rs +++ b/crates/source_gen/src/lexer/generated.rs @@ -78,6 +78,8 @@ pub enum TokenKind { AnnotationsKw, #[token("anyschema", ignore(case))] AnyschemaKw, + #[token("apply", ignore(case))] + ApplyKw, #[token("array", ignore(case))] ArrayKw, #[token("as", ignore(case))] @@ -160,6 +162,8 @@ pub enum TokenKind { ContextKw, #[token("create", ignore(case))] CreateKw, + #[token("cross", ignore(case))] + CrossKw, #[token("crossedition", ignore(case))] CrosseditionKw, #[token("cube", ignore(case))] @@ -258,6 +262,8 @@ pub enum TokenKind { ForwardKw, #[token("from", ignore(case))] FromKw, + #[token("full", ignore(case))] + FullKw, #[token("function", ignore(case))] FunctionKw, #[token("grant", ignore(case))] @@ -286,6 +292,8 @@ pub enum TokenKind { IndicatorKw, #[token("initially", ignore(case))] InitiallyKw, + #[token("inner", ignore(case))] + InnerKw, #[token("insert", ignore(case))] InsertKw, #[token("instead", ignore(case))] @@ -304,6 +312,8 @@ pub enum TokenKind { IsKw, #[token("java", ignore(case))] JavaKw, + #[token("join", ignore(case))] + JoinKw, #[token("key", ignore(case))] KeyKw, #[token("language", ignore(case))] @@ -312,6 +322,8 @@ pub enum TokenKind { LargeKw, #[token("last", ignore(case))] LastKw, + #[token("left", ignore(case))] + LeftKw, #[token("length", ignore(case))] LengthKw, #[token("library", ignore(case))] @@ -342,6 +354,8 @@ pub enum TokenKind { NameKw, #[token("national", ignore(case))] NationalKw, + #[token("natural", ignore(case))] + NaturalKw, #[token("nchar", ignore(case))] NcharKw, #[token("nclob", ignore(case))] @@ -400,6 +414,8 @@ pub enum TokenKind { OthersKw, #[token("out", ignore(case))] OutKw, + #[token("outer", ignore(case))] + OuterKw, #[token("package", ignore(case))] PackageKw, #[token("parallel_enable", ignore(case))] @@ -408,6 +424,8 @@ pub enum TokenKind { ParametersKw, #[token("parent", ignore(case))] ParentKw, + #[token("partition", ignore(case))] + PartitionKw, #[token("pipelined", ignore(case))] PipelinedKw, #[token("plpgsql", ignore(case))] @@ -468,6 +486,8 @@ pub enum TokenKind { RevokeKw, #[token("rollup", ignore(case))] RollupKw, + #[token("right", ignore(case))] + RightKw, #[token("row", ignore(case))] RowKw, #[token("rowid", ignore(case))] @@ -638,4 +658,4 @@ impl std::fmt::Display for TokenKind { } } #[macro_export] -macro_rules ! T { [comment] => { TokenKind :: Comment } ; [whitespace] => { TokenKind :: Whitespace } ; ["$$"] => { TokenKind :: DollarQuote } ; [:=] => { TokenKind :: Assign } ; [*] => { TokenKind :: Asterisk } ; [,] => { TokenKind :: Comma } ; [comparison] => { TokenKind :: Comparison } ; [.] => { TokenKind :: Dot } ; [..] => { TokenKind :: DoubleDot } ; [||] => { TokenKind :: DoublePipe } ; [=] => { TokenKind :: Equals } ; [!] => { TokenKind :: Exclam } ; ["("] => { TokenKind :: LParen } ; [-] => { TokenKind :: Minus } ; [(+)] => { TokenKind :: OracleJoin } ; [%] => { TokenKind :: Percentage } ; [+] => { TokenKind :: Plus } ; [")"] => { TokenKind :: RParen } ; [;] => { TokenKind :: Semicolon } ; [/] => { TokenKind :: Slash } ; [int_literal] => { TokenKind :: Integer } ; [decimal_literal] => { TokenKind :: Decimal } ; [unquoted_ident] => { TokenKind :: UnquotedIdent } ; [quoted_ident] => { TokenKind :: QuotedIdent } ; [quoted_literal] => { TokenKind :: QuotedLiteral } ; [bind_var] => { TokenKind :: BindVar } ; [add] => { TokenKind :: AddKw } ; [after] => { TokenKind :: AfterKw } ; [agent] => { TokenKind :: AgentKw } ; [all] => { TokenKind :: AllKw } ; [allow] => { TokenKind :: AllowKw } ; [alter] => { TokenKind :: AlterKw } ; [analyze] => { TokenKind :: AnalyzeKw } ; [and] => { TokenKind :: AndKw } ; [annotations] => { TokenKind :: AnnotationsKw } ; [anyschema] => { TokenKind :: AnyschemaKw } ; [array] => { TokenKind :: ArrayKw } ; [as] => { TokenKind :: AsKw } ; [asc] => { TokenKind :: AscKw } ; [associate] => { TokenKind :: AssociateKw } ; [audit] => { TokenKind :: AuditKw } ; [before] => { TokenKind :: BeforeKw } ; [begin] => { TokenKind :: BeginKw } ; [bequeath] => { TokenKind :: BequeathKw } ; [between] => { TokenKind :: BetweenKw } ; [bfile] => { TokenKind :: BfileKw } ; [binary] => { TokenKind :: BinaryKw } ; [binary_double] => { TokenKind :: BinaryDoubleKw } ; [binary_float] => { TokenKind :: BinaryFloatKw } ; [binary_integer] => { TokenKind :: BinaryIntegerKw } ; [blob] => { TokenKind :: BlobKw } ; [body] => { TokenKind :: BodyKw } ; [bulk] => { TokenKind :: BulkKw } ; [by] => { TokenKind :: ByKw } ; [byte] => { TokenKind :: ByteKw } ; [call] => { TokenKind :: CallKw } ; [cascade] => { TokenKind :: CascadeKw } ; [c] => { TokenKind :: CKw } ; [char] => { TokenKind :: CharKw } ; [character] => { TokenKind :: CharacterKw } ; [charsetform] => { TokenKind :: CharsetformKw } ; [charsetid] => { TokenKind :: CharsetidKw } ; [check] => { TokenKind :: CheckKw } ; [clob] => { TokenKind :: ClobKw } ; [clone] => { TokenKind :: CloneKw } ; [collation] => { TokenKind :: CollationKw } ; [collect] => { TokenKind :: CollectKw } ; [comment] => { TokenKind :: CommentKw } ; [connect] => { TokenKind :: ConnectKw } ; [connect_by_root] => { TokenKind :: ConnectByRootKw } ; [constant] => { TokenKind :: ConstantKw } ; [constraint] => { TokenKind :: ConstraintKw } ; [container] => { TokenKind :: ContainerKw } ; [container_map] => { TokenKind :: ContainerMapKw } ; [containers_default] => { TokenKind :: ContainersDefaultKw } ; [context] => { TokenKind :: ContextKw } ; [create] => { TokenKind :: CreateKw } ; [crossedition] => { TokenKind :: CrosseditionKw } ; [cube] => { TokenKind :: CubeKw } ; [current_user] => { TokenKind :: CurrentUserKw } ; [cursor] => { TokenKind :: CursorKw } ; [data] => { TokenKind :: DataKw } ; [database] => { TokenKind :: DatabaseKw } ; [date] => { TokenKind :: DateKw } ; [day] => { TokenKind :: DayKw } ; [db_role_change] => { TokenKind :: DbRoleChangeKw } ; [ddl] => { TokenKind :: DdlKw } ; [dec] => { TokenKind :: DecKw } ; [decimal] => { TokenKind :: DecimalKw } ; [declare] => { TokenKind :: DeclareKw } ; [default] => { TokenKind :: DefaultKw } ; [deferrable] => { TokenKind :: DeferrableKw } ; [deferred] => { TokenKind :: DeferredKw } ; [definer] => { TokenKind :: DefinerKw } ; [delete] => { TokenKind :: DeleteKw } ; [desc] => { TokenKind :: DescKw } ; [deterministic] => { TokenKind :: DeterministicKw } ; [disable] => { TokenKind :: DisableKw } ; [disallow] => { TokenKind :: DisallowKw } ; [disassociate] => { TokenKind :: DisassociateKw } ; [double] => { TokenKind :: DoubleKw } ; [drop] => { TokenKind :: DropKw } ; [duration] => { TokenKind :: DurationKw } ; [each] => { TokenKind :: EachKw } ; [editionable] => { TokenKind :: EditionableKw } ; [editioning] => { TokenKind :: EditioningKw } ; [element] => { TokenKind :: ElementKw } ; [else] => { TokenKind :: ElseKw } ; [elsif] => { TokenKind :: ElsifKw } ; [enable] => { TokenKind :: EnableKw } ; [end] => { TokenKind :: EndKw } ; [env] => { TokenKind :: EnvKw } ; [exception] => { TokenKind :: ExceptionKw } ; [exceptions] => { TokenKind :: ExceptionsKw } ; [execute] => { TokenKind :: ExecuteKw } ; [exists] => { TokenKind :: ExistsKw } ; [extended] => { TokenKind :: ExtendedKw } ; [external] => { TokenKind :: ExternalKw } ; [first] => { TokenKind :: FirstKw } ; [float] => { TokenKind :: FloatKw } ; [follows] => { TokenKind :: FollowsKw } ; [for] => { TokenKind :: ForKw } ; [force] => { TokenKind :: ForceKw } ; [foreign] => { TokenKind :: ForeignKw } ; [forward] => { TokenKind :: ForwardKw } ; [from] => { TokenKind :: FromKw } ; [function] => { TokenKind :: FunctionKw } ; [grant] => { TokenKind :: GrantKw } ; [group] => { TokenKind :: GroupKw } ; [grouping] => { TokenKind :: GroupingKw } ; [having] => { TokenKind :: HavingKw } ; [id] => { TokenKind :: IdKw } ; [identifier] => { TokenKind :: IdentifierKw } ; [if] => { TokenKind :: IfKw } ; [ilike] => { TokenKind :: IlikeKw } ; [immediate] => { TokenKind :: ImmediateKw } ; [in] => { TokenKind :: InKw } ; [index] => { TokenKind :: IndexKw } ; [indicator] => { TokenKind :: IndicatorKw } ; [initially] => { TokenKind :: InitiallyKw } ; [insert] => { TokenKind :: InsertKw } ; [instead] => { TokenKind :: InsteadKw } ; [int] => { TokenKind :: IntKw } ; [integer] => { TokenKind :: IntegerKw } ; [interval] => { TokenKind :: IntervalKw } ; [into] => { TokenKind :: IntoKw } ; [invisible] => { TokenKind :: InvisibleKw } ; [is] => { TokenKind :: IsKw } ; [java] => { TokenKind :: JavaKw } ; [key] => { TokenKind :: KeyKw } ; [language] => { TokenKind :: LanguageKw } ; [large] => { TokenKind :: LargeKw } ; [last] => { TokenKind :: LastKw } ; [length] => { TokenKind :: LengthKw } ; [library] => { TokenKind :: LibraryKw } ; [like] => { TokenKind :: LikeKw } ; [lobs] => { TokenKind :: LobsKw } ; [local] => { TokenKind :: LocalKw } ; [logoff] => { TokenKind :: LogoffKw } ; [logon] => { TokenKind :: LogonKw } ; [long] => { TokenKind :: LongKw } ; [maxlen] => { TokenKind :: MaxlenKw } ; [metadata] => { TokenKind :: MetadataKw } ; [mle] => { TokenKind :: MleKw } ; [module] => { TokenKind :: ModuleKw } ; [month] => { TokenKind :: MonthKw } ; [name] => { TokenKind :: NameKw } ; [national] => { TokenKind :: NationalKw } ; [nchar] => { TokenKind :: NcharKw } ; [nclob] => { TokenKind :: NclobKw } ; [new] => { TokenKind :: NewKw } ; [no] => { TokenKind :: NoKw } ; [noaudit] => { TokenKind :: NoauditKw } ; [nocopy] => { TokenKind :: NocopyKw } ; [nocycle] => { TokenKind :: NocycleKw } ; [none] => { TokenKind :: NoneKw } ; [noneditionable] => { TokenKind :: NoneditionableKw } ; [nonschema] => { TokenKind :: NonschemaKw } ; [noprecheck] => { TokenKind :: NoprecheckKw } ; [norely] => { TokenKind :: NorelyKw } ; [not] => { TokenKind :: NotKw } ; [novalidate] => { TokenKind :: NovalidateKw } ; [null] => { TokenKind :: NullKw } ; [nulls] => { TokenKind :: NullsKw } ; [number] => { TokenKind :: NumberKw } ; [numeric] => { TokenKind :: NumericKw } ; [nvarchar2] => { TokenKind :: Nvarchar2Kw } ; [object] => { TokenKind :: ObjectKw } ; [of] => { TokenKind :: OfKw } ; [old] => { TokenKind :: OldKw } ; [on] => { TokenKind :: OnKw } ; [only] => { TokenKind :: OnlyKw } ; [option] => { TokenKind :: OptionKw } ; [or] => { TokenKind :: OrKw } ; [order] => { TokenKind :: OrderKw } ; [others] => { TokenKind :: OthersKw } ; [out] => { TokenKind :: OutKw } ; [package] => { TokenKind :: PackageKw } ; [parallel_enable] => { TokenKind :: ParallelEnableKw } ; [parameters] => { TokenKind :: ParametersKw } ; [parent] => { TokenKind :: ParentKw } ; [pipelined] => { TokenKind :: PipelinedKw } ; [plpgsql] => { TokenKind :: PlpgsqlKw } ; [pls_integer] => { TokenKind :: PlsIntegerKw } ; [pluggable] => { TokenKind :: PluggableKw } ; [precedes] => { TokenKind :: PrecedesKw } ; [precheck] => { TokenKind :: PrecheckKw } ; [precision] => { TokenKind :: PrecisionKw } ; [prior] => { TokenKind :: PriorKw } ; [primary] => { TokenKind :: PrimaryKw } ; [procedure] => { TokenKind :: ProcedureKw } ; [range] => { TokenKind :: RangeKw } ; [raise] => { TokenKind :: RaiseKw } ; [raw] => { TokenKind :: RawKw } ; [read] => { TokenKind :: ReadKw } ; [real] => { TokenKind :: RealKw } ; [record] => { TokenKind :: RecordKw } ; [ref] => { TokenKind :: RefKw } ; [reference] => { TokenKind :: ReferenceKw } ; [references] => { TokenKind :: ReferencesKw } ; [referencing] => { TokenKind :: ReferencingKw } ; [relies_on] => { TokenKind :: ReliesOnKw } ; [rely] => { TokenKind :: RelyKw } ; [rename] => { TokenKind :: RenameKw } ; [replace] => { TokenKind :: ReplaceKw } ; [result_cache] => { TokenKind :: ResultCacheKw } ; [return] => { TokenKind :: ReturnKw } ; [returning] => { TokenKind :: ReturningKw } ; [reverse] => { TokenKind :: ReverseKw } ; [revoke] => { TokenKind :: RevokeKw } ; [rollup] => { TokenKind :: RollupKw } ; [row] => { TokenKind :: RowKw } ; [rowid] => { TokenKind :: RowidKw } ; [rowtype] => { TokenKind :: RowtypeKw } ; [schema] => { TokenKind :: SchemaKw } ; [scope] => { TokenKind :: ScopeKw } ; [second] => { TokenKind :: SecondKw } ; [select] => { TokenKind :: SelectKw } ; [self] => { TokenKind :: SelfKw } ; [servererror] => { TokenKind :: ServererrorKw } ; [set] => { TokenKind :: SetKw } ; [sets] => { TokenKind :: SetsKw } ; [sharing] => { TokenKind :: SharingKw } ; [shutdown] => { TokenKind :: ShutdownKw } ; [siblings] => { TokenKind :: SiblingsKw } ; [signature] => { TokenKind :: SignatureKw } ; [smallint] => { TokenKind :: SmallintKw } ; [starts] => { TokenKind :: StartsKw } ; [startup] => { TokenKind :: StartupKw } ; [statistics] => { TokenKind :: StatisticsKw } ; [store] => { TokenKind :: StoreKw } ; [string] => { TokenKind :: StringKw } ; [struct] => { TokenKind :: StructKw } ; [subtype] => { TokenKind :: SubtypeKw } ; [suspend] => { TokenKind :: SuspendKw } ; [table] => { TokenKind :: TableKw } ; [tables] => { TokenKind :: TablesKw } ; [tdo] => { TokenKind :: TdoKw } ; [then] => { TokenKind :: ThenKw } ; [time] => { TokenKind :: TimeKw } ; [timestamp] => { TokenKind :: TimestampKw } ; [to] => { TokenKind :: ToKw } ; [trigger] => { TokenKind :: TriggerKw } ; [truncate] => { TokenKind :: TruncateKw } ; [type] => { TokenKind :: TypeKw } ; [under] => { TokenKind :: UnderKw } ; [unique] => { TokenKind :: UniqueKw } ; [unplug] => { TokenKind :: UnplugKw } ; [update] => { TokenKind :: UpdateKw } ; [urowid] => { TokenKind :: UrowidKw } ; [using] => { TokenKind :: UsingKw } ; [validate] => { TokenKind :: ValidateKw } ; [values] => { TokenKind :: ValuesKw } ; [varchar] => { TokenKind :: VarcharKw } ; [varchar2] => { TokenKind :: Varchar2Kw } ; [varray] => { TokenKind :: VarrayKw } ; [varrays] => { TokenKind :: VarraysKw } ; [varying] => { TokenKind :: VaryingKw } ; [view] => { TokenKind :: ViewKw } ; [visible] => { TokenKind :: VisibleKw } ; [when] => { TokenKind :: WhenKw } ; [where] => { TokenKind :: WhereKw } ; [with] => { TokenKind :: WithKw } ; [xmlschema] => { TokenKind :: XmlschemaKw } ; [xmltype] => { TokenKind :: XmltypeKw } ; [year] => { TokenKind :: YearKw } ; [zone] => { TokenKind :: ZoneKw } ; [EOF] => { TokenKind :: Eof } ; } +macro_rules ! T { [comment] => { TokenKind :: Comment } ; [whitespace] => { TokenKind :: Whitespace } ; ["$$"] => { TokenKind :: DollarQuote } ; [:=] => { TokenKind :: Assign } ; [*] => { TokenKind :: Asterisk } ; [,] => { TokenKind :: Comma } ; [comparison] => { TokenKind :: Comparison } ; [.] => { TokenKind :: Dot } ; [..] => { TokenKind :: DoubleDot } ; [||] => { TokenKind :: DoublePipe } ; [=] => { TokenKind :: Equals } ; [!] => { TokenKind :: Exclam } ; ["("] => { TokenKind :: LParen } ; [-] => { TokenKind :: Minus } ; [(+)] => { TokenKind :: OracleJoin } ; [%] => { TokenKind :: Percentage } ; [+] => { TokenKind :: Plus } ; [")"] => { TokenKind :: RParen } ; [;] => { TokenKind :: Semicolon } ; [/] => { TokenKind :: Slash } ; [int_literal] => { TokenKind :: Integer } ; [decimal_literal] => { TokenKind :: Decimal } ; [unquoted_ident] => { TokenKind :: UnquotedIdent } ; [quoted_ident] => { TokenKind :: QuotedIdent } ; [quoted_literal] => { TokenKind :: QuotedLiteral } ; [bind_var] => { TokenKind :: BindVar } ; [add] => { TokenKind :: AddKw } ; [after] => { TokenKind :: AfterKw } ; [agent] => { TokenKind :: AgentKw } ; [all] => { TokenKind :: AllKw } ; [allow] => { TokenKind :: AllowKw } ; [alter] => { TokenKind :: AlterKw } ; [analyze] => { TokenKind :: AnalyzeKw } ; [and] => { TokenKind :: AndKw } ; [annotations] => { TokenKind :: AnnotationsKw } ; [anyschema] => { TokenKind :: AnyschemaKw } ; [apply] => { TokenKind :: ApplyKw } ; [array] => { TokenKind :: ArrayKw } ; [as] => { TokenKind :: AsKw } ; [asc] => { TokenKind :: AscKw } ; [associate] => { TokenKind :: AssociateKw } ; [audit] => { TokenKind :: AuditKw } ; [before] => { TokenKind :: BeforeKw } ; [begin] => { TokenKind :: BeginKw } ; [bequeath] => { TokenKind :: BequeathKw } ; [between] => { TokenKind :: BetweenKw } ; [bfile] => { TokenKind :: BfileKw } ; [binary] => { TokenKind :: BinaryKw } ; [binary_double] => { TokenKind :: BinaryDoubleKw } ; [binary_float] => { TokenKind :: BinaryFloatKw } ; [binary_integer] => { TokenKind :: BinaryIntegerKw } ; [blob] => { TokenKind :: BlobKw } ; [body] => { TokenKind :: BodyKw } ; [bulk] => { TokenKind :: BulkKw } ; [by] => { TokenKind :: ByKw } ; [byte] => { TokenKind :: ByteKw } ; [call] => { TokenKind :: CallKw } ; [cascade] => { TokenKind :: CascadeKw } ; [c] => { TokenKind :: CKw } ; [char] => { TokenKind :: CharKw } ; [character] => { TokenKind :: CharacterKw } ; [charsetform] => { TokenKind :: CharsetformKw } ; [charsetid] => { TokenKind :: CharsetidKw } ; [check] => { TokenKind :: CheckKw } ; [clob] => { TokenKind :: ClobKw } ; [clone] => { TokenKind :: CloneKw } ; [collation] => { TokenKind :: CollationKw } ; [collect] => { TokenKind :: CollectKw } ; [comment] => { TokenKind :: CommentKw } ; [connect] => { TokenKind :: ConnectKw } ; [connect_by_root] => { TokenKind :: ConnectByRootKw } ; [constant] => { TokenKind :: ConstantKw } ; [constraint] => { TokenKind :: ConstraintKw } ; [container] => { TokenKind :: ContainerKw } ; [container_map] => { TokenKind :: ContainerMapKw } ; [containers_default] => { TokenKind :: ContainersDefaultKw } ; [context] => { TokenKind :: ContextKw } ; [create] => { TokenKind :: CreateKw } ; [cross] => { TokenKind :: CrossKw } ; [crossedition] => { TokenKind :: CrosseditionKw } ; [cube] => { TokenKind :: CubeKw } ; [current_user] => { TokenKind :: CurrentUserKw } ; [cursor] => { TokenKind :: CursorKw } ; [data] => { TokenKind :: DataKw } ; [database] => { TokenKind :: DatabaseKw } ; [date] => { TokenKind :: DateKw } ; [day] => { TokenKind :: DayKw } ; [db_role_change] => { TokenKind :: DbRoleChangeKw } ; [ddl] => { TokenKind :: DdlKw } ; [dec] => { TokenKind :: DecKw } ; [decimal] => { TokenKind :: DecimalKw } ; [declare] => { TokenKind :: DeclareKw } ; [default] => { TokenKind :: DefaultKw } ; [deferrable] => { TokenKind :: DeferrableKw } ; [deferred] => { TokenKind :: DeferredKw } ; [definer] => { TokenKind :: DefinerKw } ; [delete] => { TokenKind :: DeleteKw } ; [desc] => { TokenKind :: DescKw } ; [deterministic] => { TokenKind :: DeterministicKw } ; [disable] => { TokenKind :: DisableKw } ; [disallow] => { TokenKind :: DisallowKw } ; [disassociate] => { TokenKind :: DisassociateKw } ; [double] => { TokenKind :: DoubleKw } ; [drop] => { TokenKind :: DropKw } ; [duration] => { TokenKind :: DurationKw } ; [each] => { TokenKind :: EachKw } ; [editionable] => { TokenKind :: EditionableKw } ; [editioning] => { TokenKind :: EditioningKw } ; [element] => { TokenKind :: ElementKw } ; [else] => { TokenKind :: ElseKw } ; [elsif] => { TokenKind :: ElsifKw } ; [enable] => { TokenKind :: EnableKw } ; [end] => { TokenKind :: EndKw } ; [env] => { TokenKind :: EnvKw } ; [exception] => { TokenKind :: ExceptionKw } ; [exceptions] => { TokenKind :: ExceptionsKw } ; [execute] => { TokenKind :: ExecuteKw } ; [exists] => { TokenKind :: ExistsKw } ; [extended] => { TokenKind :: ExtendedKw } ; [external] => { TokenKind :: ExternalKw } ; [first] => { TokenKind :: FirstKw } ; [float] => { TokenKind :: FloatKw } ; [follows] => { TokenKind :: FollowsKw } ; [for] => { TokenKind :: ForKw } ; [force] => { TokenKind :: ForceKw } ; [foreign] => { TokenKind :: ForeignKw } ; [forward] => { TokenKind :: ForwardKw } ; [from] => { TokenKind :: FromKw } ; [full] => { TokenKind :: FullKw } ; [function] => { TokenKind :: FunctionKw } ; [grant] => { TokenKind :: GrantKw } ; [group] => { TokenKind :: GroupKw } ; [grouping] => { TokenKind :: GroupingKw } ; [having] => { TokenKind :: HavingKw } ; [id] => { TokenKind :: IdKw } ; [identifier] => { TokenKind :: IdentifierKw } ; [if] => { TokenKind :: IfKw } ; [ilike] => { TokenKind :: IlikeKw } ; [immediate] => { TokenKind :: ImmediateKw } ; [in] => { TokenKind :: InKw } ; [index] => { TokenKind :: IndexKw } ; [indicator] => { TokenKind :: IndicatorKw } ; [initially] => { TokenKind :: InitiallyKw } ; [inner] => { TokenKind :: InnerKw } ; [insert] => { TokenKind :: InsertKw } ; [instead] => { TokenKind :: InsteadKw } ; [int] => { TokenKind :: IntKw } ; [integer] => { TokenKind :: IntegerKw } ; [interval] => { TokenKind :: IntervalKw } ; [into] => { TokenKind :: IntoKw } ; [invisible] => { TokenKind :: InvisibleKw } ; [is] => { TokenKind :: IsKw } ; [java] => { TokenKind :: JavaKw } ; [join] => { TokenKind :: JoinKw } ; [key] => { TokenKind :: KeyKw } ; [language] => { TokenKind :: LanguageKw } ; [large] => { TokenKind :: LargeKw } ; [last] => { TokenKind :: LastKw } ; [left] => { TokenKind :: LeftKw } ; [length] => { TokenKind :: LengthKw } ; [library] => { TokenKind :: LibraryKw } ; [like] => { TokenKind :: LikeKw } ; [lobs] => { TokenKind :: LobsKw } ; [local] => { TokenKind :: LocalKw } ; [logoff] => { TokenKind :: LogoffKw } ; [logon] => { TokenKind :: LogonKw } ; [long] => { TokenKind :: LongKw } ; [maxlen] => { TokenKind :: MaxlenKw } ; [metadata] => { TokenKind :: MetadataKw } ; [mle] => { TokenKind :: MleKw } ; [module] => { TokenKind :: ModuleKw } ; [month] => { TokenKind :: MonthKw } ; [name] => { TokenKind :: NameKw } ; [national] => { TokenKind :: NationalKw } ; [natural] => { TokenKind :: NaturalKw } ; [nchar] => { TokenKind :: NcharKw } ; [nclob] => { TokenKind :: NclobKw } ; [new] => { TokenKind :: NewKw } ; [no] => { TokenKind :: NoKw } ; [noaudit] => { TokenKind :: NoauditKw } ; [nocopy] => { TokenKind :: NocopyKw } ; [nocycle] => { TokenKind :: NocycleKw } ; [none] => { TokenKind :: NoneKw } ; [noneditionable] => { TokenKind :: NoneditionableKw } ; [nonschema] => { TokenKind :: NonschemaKw } ; [noprecheck] => { TokenKind :: NoprecheckKw } ; [norely] => { TokenKind :: NorelyKw } ; [not] => { TokenKind :: NotKw } ; [novalidate] => { TokenKind :: NovalidateKw } ; [null] => { TokenKind :: NullKw } ; [nulls] => { TokenKind :: NullsKw } ; [number] => { TokenKind :: NumberKw } ; [numeric] => { TokenKind :: NumericKw } ; [nvarchar2] => { TokenKind :: Nvarchar2Kw } ; [object] => { TokenKind :: ObjectKw } ; [of] => { TokenKind :: OfKw } ; [old] => { TokenKind :: OldKw } ; [on] => { TokenKind :: OnKw } ; [only] => { TokenKind :: OnlyKw } ; [option] => { TokenKind :: OptionKw } ; [or] => { TokenKind :: OrKw } ; [order] => { TokenKind :: OrderKw } ; [others] => { TokenKind :: OthersKw } ; [out] => { TokenKind :: OutKw } ; [outer] => { TokenKind :: OuterKw } ; [package] => { TokenKind :: PackageKw } ; [parallel_enable] => { TokenKind :: ParallelEnableKw } ; [parameters] => { TokenKind :: ParametersKw } ; [parent] => { TokenKind :: ParentKw } ; [partition] => { TokenKind :: PartitionKw } ; [pipelined] => { TokenKind :: PipelinedKw } ; [plpgsql] => { TokenKind :: PlpgsqlKw } ; [pls_integer] => { TokenKind :: PlsIntegerKw } ; [pluggable] => { TokenKind :: PluggableKw } ; [precedes] => { TokenKind :: PrecedesKw } ; [precheck] => { TokenKind :: PrecheckKw } ; [precision] => { TokenKind :: PrecisionKw } ; [prior] => { TokenKind :: PriorKw } ; [primary] => { TokenKind :: PrimaryKw } ; [procedure] => { TokenKind :: ProcedureKw } ; [range] => { TokenKind :: RangeKw } ; [raise] => { TokenKind :: RaiseKw } ; [raw] => { TokenKind :: RawKw } ; [read] => { TokenKind :: ReadKw } ; [real] => { TokenKind :: RealKw } ; [record] => { TokenKind :: RecordKw } ; [ref] => { TokenKind :: RefKw } ; [reference] => { TokenKind :: ReferenceKw } ; [references] => { TokenKind :: ReferencesKw } ; [referencing] => { TokenKind :: ReferencingKw } ; [relies_on] => { TokenKind :: ReliesOnKw } ; [rely] => { TokenKind :: RelyKw } ; [rename] => { TokenKind :: RenameKw } ; [replace] => { TokenKind :: ReplaceKw } ; [result_cache] => { TokenKind :: ResultCacheKw } ; [return] => { TokenKind :: ReturnKw } ; [returning] => { TokenKind :: ReturningKw } ; [reverse] => { TokenKind :: ReverseKw } ; [revoke] => { TokenKind :: RevokeKw } ; [rollup] => { TokenKind :: RollupKw } ; [right] => { TokenKind :: RightKw } ; [row] => { TokenKind :: RowKw } ; [rowid] => { TokenKind :: RowidKw } ; [rowtype] => { TokenKind :: RowtypeKw } ; [schema] => { TokenKind :: SchemaKw } ; [scope] => { TokenKind :: ScopeKw } ; [second] => { TokenKind :: SecondKw } ; [select] => { TokenKind :: SelectKw } ; [self] => { TokenKind :: SelfKw } ; [servererror] => { TokenKind :: ServererrorKw } ; [set] => { TokenKind :: SetKw } ; [sets] => { TokenKind :: SetsKw } ; [sharing] => { TokenKind :: SharingKw } ; [shutdown] => { TokenKind :: ShutdownKw } ; [siblings] => { TokenKind :: SiblingsKw } ; [signature] => { TokenKind :: SignatureKw } ; [smallint] => { TokenKind :: SmallintKw } ; [starts] => { TokenKind :: StartsKw } ; [startup] => { TokenKind :: StartupKw } ; [statistics] => { TokenKind :: StatisticsKw } ; [store] => { TokenKind :: StoreKw } ; [string] => { TokenKind :: StringKw } ; [struct] => { TokenKind :: StructKw } ; [subtype] => { TokenKind :: SubtypeKw } ; [suspend] => { TokenKind :: SuspendKw } ; [table] => { TokenKind :: TableKw } ; [tables] => { TokenKind :: TablesKw } ; [tdo] => { TokenKind :: TdoKw } ; [then] => { TokenKind :: ThenKw } ; [time] => { TokenKind :: TimeKw } ; [timestamp] => { TokenKind :: TimestampKw } ; [to] => { TokenKind :: ToKw } ; [trigger] => { TokenKind :: TriggerKw } ; [truncate] => { TokenKind :: TruncateKw } ; [type] => { TokenKind :: TypeKw } ; [under] => { TokenKind :: UnderKw } ; [unique] => { TokenKind :: UniqueKw } ; [unplug] => { TokenKind :: UnplugKw } ; [update] => { TokenKind :: UpdateKw } ; [urowid] => { TokenKind :: UrowidKw } ; [using] => { TokenKind :: UsingKw } ; [validate] => { TokenKind :: ValidateKw } ; [values] => { TokenKind :: ValuesKw } ; [varchar] => { TokenKind :: VarcharKw } ; [varchar2] => { TokenKind :: Varchar2Kw } ; [varray] => { TokenKind :: VarrayKw } ; [varrays] => { TokenKind :: VarraysKw } ; [varying] => { TokenKind :: VaryingKw } ; [view] => { TokenKind :: ViewKw } ; [visible] => { TokenKind :: VisibleKw } ; [when] => { TokenKind :: WhenKw } ; [where] => { TokenKind :: WhereKw } ; [with] => { TokenKind :: WithKw } ; [xmlschema] => { TokenKind :: XmlschemaKw } ; [xmltype] => { TokenKind :: XmltypeKw } ; [year] => { TokenKind :: YearKw } ; [zone] => { TokenKind :: ZoneKw } ; [EOF] => { TokenKind :: Eof } ; } diff --git a/crates/source_gen/src/syntax/generated.rs b/crates/source_gen/src/syntax/generated.rs index 35282d6..f340d77 100644 --- a/crates/source_gen/src/syntax/generated.rs +++ b/crates/source_gen/src/syntax/generated.rs @@ -58,6 +58,10 @@ pub enum SyntaxKind { Connect, #[doc = "A node that marks a full constraint"] Constraint, + #[doc = "A node that contains a full CROSS JOIN clause"] + CrossJoinClause, + #[doc = "A node that contains a full cross outer apply clause"] + CrossOuterApplyClause, #[doc = "A node containing a cursor parameter declaration"] CursorParameterDeclaration, #[doc = "A node containing cursor parameter declarations"] @@ -102,12 +106,16 @@ pub enum SyntaxKind { Ident, #[doc = "An identifier group, consisting of multiple idents"] IdentGroup, + #[doc = "A node that contains an INNER JOIN clause"] + InnerJoinClause, #[doc = "A node that marks a full INSERT statement"] InsertStmt, #[doc = "Any integer, positive and negative"] Integer, #[doc = "A node that contains an `INTO` clause of a SELECT statement"] IntoClause, + #[doc = "A node that contains a JOIN clause"] + JoinClause, #[doc = "A SQL keyword, e.g. `CREATE`"] Keyword, #[doc = "Represents a logical SQL operator (AND, OR, NOT)"] @@ -116,18 +124,24 @@ pub enum SyntaxKind { LParen, #[doc = "A minus `-`"] Minus, + #[doc = "A node containing an NATURAL JOIN clause"] + NaturalJoinClause, #[doc = "Unary logical operator NOT"] Not, #[doc = "Logical operator OR"] Or, #[doc = "A node containing a full order by clause"] OrderByClause, + #[doc = "A node containing a full OUTER JOIN clause"] + OuterJoinClause, #[doc = "A node that marks a full CREATE PACKAGE BODY block"] Package, #[doc = "A single Param node, consisting of name & type"] Param, #[doc = "A node that consists of multiple parameters"] ParamList, + #[doc = "A node that contains a PARTITION BY clause"] + PartitionByClause, #[doc = "Percentage symbol"] Percentage, #[doc = "A plus `+`"] @@ -235,6 +249,7 @@ impl From for SyntaxKind { TokenKind::AndKw => SyntaxKind::Keyword, TokenKind::AnnotationsKw => SyntaxKind::Keyword, TokenKind::AnyschemaKw => SyntaxKind::Keyword, + TokenKind::ApplyKw => SyntaxKind::Keyword, TokenKind::ArrayKw => SyntaxKind::Keyword, TokenKind::AsKw => SyntaxKind::Keyword, TokenKind::AscKw => SyntaxKind::Keyword, @@ -276,6 +291,7 @@ impl From for SyntaxKind { TokenKind::ContainersDefaultKw => SyntaxKind::Keyword, TokenKind::ContextKw => SyntaxKind::Keyword, TokenKind::CreateKw => SyntaxKind::Keyword, + TokenKind::CrossKw => SyntaxKind::Keyword, TokenKind::CrosseditionKw => SyntaxKind::Keyword, TokenKind::CubeKw => SyntaxKind::Keyword, TokenKind::CurrentUserKw => SyntaxKind::Keyword, @@ -325,6 +341,7 @@ impl From for SyntaxKind { TokenKind::ForeignKw => SyntaxKind::Keyword, TokenKind::ForwardKw => SyntaxKind::Keyword, TokenKind::FromKw => SyntaxKind::Keyword, + TokenKind::FullKw => SyntaxKind::Keyword, TokenKind::FunctionKw => SyntaxKind::Keyword, TokenKind::GrantKw => SyntaxKind::Keyword, TokenKind::GroupKw => SyntaxKind::Keyword, @@ -339,6 +356,7 @@ impl From for SyntaxKind { TokenKind::IndexKw => SyntaxKind::Keyword, TokenKind::IndicatorKw => SyntaxKind::Keyword, TokenKind::InitiallyKw => SyntaxKind::Keyword, + TokenKind::InnerKw => SyntaxKind::Keyword, TokenKind::InsertKw => SyntaxKind::Keyword, TokenKind::InsteadKw => SyntaxKind::Keyword, TokenKind::IntKw => SyntaxKind::Keyword, @@ -348,10 +366,12 @@ impl From for SyntaxKind { TokenKind::InvisibleKw => SyntaxKind::Keyword, TokenKind::IsKw => SyntaxKind::Keyword, TokenKind::JavaKw => SyntaxKind::Keyword, + TokenKind::JoinKw => SyntaxKind::Keyword, TokenKind::KeyKw => SyntaxKind::Keyword, TokenKind::LanguageKw => SyntaxKind::Keyword, TokenKind::LargeKw => SyntaxKind::Keyword, TokenKind::LastKw => SyntaxKind::Keyword, + TokenKind::LeftKw => SyntaxKind::Keyword, TokenKind::LengthKw => SyntaxKind::Keyword, TokenKind::LibraryKw => SyntaxKind::Keyword, TokenKind::LikeKw => SyntaxKind::ComparisonOp, @@ -367,6 +387,7 @@ impl From for SyntaxKind { TokenKind::MonthKw => SyntaxKind::Keyword, TokenKind::NameKw => SyntaxKind::Keyword, TokenKind::NationalKw => SyntaxKind::Keyword, + TokenKind::NaturalKw => SyntaxKind::Keyword, TokenKind::NcharKw => SyntaxKind::Keyword, TokenKind::NclobKw => SyntaxKind::Keyword, TokenKind::NewKw => SyntaxKind::Keyword, @@ -396,10 +417,12 @@ impl From for SyntaxKind { TokenKind::OrderKw => SyntaxKind::Keyword, TokenKind::OthersKw => SyntaxKind::Keyword, TokenKind::OutKw => SyntaxKind::Keyword, + TokenKind::OuterKw => SyntaxKind::Keyword, TokenKind::PackageKw => SyntaxKind::Keyword, TokenKind::ParallelEnableKw => SyntaxKind::Keyword, TokenKind::ParametersKw => SyntaxKind::Keyword, TokenKind::ParentKw => SyntaxKind::Keyword, + TokenKind::PartitionKw => SyntaxKind::Keyword, TokenKind::PipelinedKw => SyntaxKind::Keyword, TokenKind::PlpgsqlKw => SyntaxKind::Keyword, TokenKind::PlsIntegerKw => SyntaxKind::Keyword, @@ -430,6 +453,7 @@ impl From for SyntaxKind { TokenKind::ReverseKw => SyntaxKind::Keyword, TokenKind::RevokeKw => SyntaxKind::Keyword, TokenKind::RollupKw => SyntaxKind::Keyword, + TokenKind::RightKw => SyntaxKind::Keyword, TokenKind::RowKw => SyntaxKind::Keyword, TokenKind::RowidKw => SyntaxKind::Keyword, TokenKind::RowtypeKw => SyntaxKind::Keyword, diff --git a/src/grammar/datatype.rs b/src/grammar/datatype.rs index c9b47a9..c131368 100644 --- a/src/grammar/datatype.rs +++ b/src/grammar/datatype.rs @@ -55,6 +55,7 @@ pub fn parse_datatype(p: &mut Parser) { | T![integer] | T![long] | T![national] + | T![natural] | T![nchar] | T![nclob] | T![number] diff --git a/src/grammar/query.rs b/src/grammar/query.rs index 0f5d747..7bfae13 100644 --- a/src/grammar/query.rs +++ b/src/grammar/query.rs @@ -172,14 +172,176 @@ pub(crate) fn parse_into_clause(p: &mut Parser, expect_into_clause: bool) { } fn parse_from_list(p: &mut Parser) { + let mut expect_join = false; + const JOIN_TOKENS: &[TokenKind] = &[ + T![join], + T!["("], + T![inner], + T![outer], + T![cross], + T![natural], + T![left], + T![right], + T![full], + ]; + safe_loop!(p, { - parse_ident(p, 1..1); - if !p.eat(T![,]) { + if !expect_join { + parse_ident(p, 1..1); + } + if JOIN_TOKENS.contains(&p.current()) { + let expect_r_param = p.eat(T!["("]); + parse_join_clause(p); + if expect_r_param { + p.expect(T![")"]); + } + } + expect_join = JOIN_TOKENS.contains(&p.current()); + + if !p.eat(T![,]) && !expect_join { break; } }); } +fn parse_join_clause(p: &mut Parser) { + p.start(SyntaxKind::JoinClause); + match p.current() { + T![join] | T![inner] => parse_inner_join_clause(p), + T![cross] => match p.nth(1) { + Some(T![apply]) => parse_cross_outer_apply_clause(p), + _ => parse_cross_join_clause(p), + }, + T![outer] => match p.nth(1) { + Some(T![apply]) => parse_cross_outer_apply_clause(p), + _ => parse_outer_join_clause(p), + }, + T![natural] => match p.nth(1) { + Some(T![full]) | Some(T![left]) | Some(T![right]) => parse_outer_join_clause(p), + Some(T![inner]) | Some(T![join]) => parse_natural_join_clause(p), + _ => (), + }, + T![full] | T![left] | T![right] => parse_outer_join_clause(p), + _ => p.error(crate::ParseErrorType::ExpectedOneOfTokens(vec![ + T![join], + T![inner], + T![cross], + T![outer], + T![natural], + T![full], + T![left], + T![right], + ])), + } + p.finish(); +} + +fn parse_inner_join_clause(p: &mut Parser) { + p.start(SyntaxKind::InnerJoinClause); + p.eat(T![inner]); + p.expect(T![join]); + parse_ident(p, 1..2); + match p.current() { + T![on] => { + p.expect(T![on]); + parse_expr(p); + } + T![using] => { + p.expect(T![using]); + p.expect(T!["("]); + safe_loop!(p, { + parse_ident(p, 1..1); + if !p.eat(T![,]) { + break; + } + }); + p.expect(T![")"]); + } + _ => (), + } + + p.finish(); +} + +fn parse_cross_join_clause(p: &mut Parser) { + p.start(SyntaxKind::CrossJoinClause); + p.expect(T![cross]); + p.expect(T![join]); + parse_ident(p, 1..2); + p.finish(); +} + +fn parse_cross_outer_apply_clause(p: &mut Parser) { + p.start(SyntaxKind::CrossOuterApplyClause); + p.expect_one_of(&[T![cross], T![outer]]); + p.expect(T![apply]); + parse_ident(p, 1..2); + p.finish(); +} + +fn parse_outer_join_clause(p: &mut Parser) { + p.start(SyntaxKind::OuterJoinClause); + if p.at(T![partition]) { + parse_partition_by_clause(p); + } + p.eat(T![natural]); + p.expect_one_of(&[T![full], T![left], T![right]]); + p.eat(T![outer]); + p.expect(T![join]); + parse_ident(p, 1..2); + if p.at(T![partition]) { + parse_partition_by_clause(p); + } + match p.current() { + T![on] => { + p.expect(T![on]); + parse_expr(p); + } + T![using] => { + p.expect(T![using]); + p.expect(T!["("]); + safe_loop!(p, { + parse_ident(p, 1..1); + if !p.eat(T![,]) { + break; + } + }); + p.expect(T![")"]); + } + _ => (), + } + + p.finish(); +} + +fn parse_natural_join_clause(p: &mut Parser) { + p.start(SyntaxKind::NaturalJoinClause); + p.expect(T![natural]); + p.eat(T![inner]); + p.expect(T![join]); + parse_ident(p, 1..2); + p.finish() +} + +pub(crate) fn parse_partition_by_clause(p: &mut Parser) { + p.start(SyntaxKind::PartitionByClause); + p.expect(T![partition]); + p.expect(T![by]); + let expect_closing_paren = p.eat(T!["("]); + safe_loop!(p, { + parse_expr(p); + + if p.eat(T![,]) { + break; + } + }); + + if expect_closing_paren { + p.expect(T![")"]); + } + p.finish(); +} + pub(crate) fn parse_where_clause(p: &mut Parser) { p.start(SyntaxKind::WhereClause); p.expect(T![where]); @@ -947,6 +1109,146 @@ Root@0..44 ); } + #[test] + fn test_simple_join() { + check( + parse( + "SELECT name, license_plate FROM employee JOIN car on employee.id=car.owner_id;", + |p| parse_query(p, false), + ), + expect![[r#" +Root@0..78 + SelectStmt@0..78 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + SelectClause@7..27 + ColumnExpr@7..11 + Expression@7..11 + IdentGroup@7..11 + Ident@7..11 "name" + Comma@11..12 "," + Whitespace@12..13 " " + ColumnExpr@13..27 + IdentGroup@13..26 + Ident@13..26 "license_plate" + Whitespace@26..27 " " + Keyword@27..31 "FROM" + Whitespace@31..32 " " + IdentGroup@32..40 + Ident@32..40 "employee" + Whitespace@40..41 " " + JoinClause@41..77 + InnerJoinClause@41..77 + Keyword@41..45 "JOIN" + Whitespace@45..46 " " + IdentGroup@46..49 + Ident@46..49 "car" + Whitespace@49..50 " " + Keyword@50..52 "on" + Whitespace@52..53 " " + Expression@53..77 + IdentGroup@53..64 + Ident@53..61 "employee" + Dot@61..62 "." + Ident@62..64 "id" + ComparisonOp@64..65 "=" + IdentGroup@65..77 + Ident@65..68 "car" + Dot@68..69 "." + Ident@69..77 "owner_id" + Semicolon@77..78 ";" +"#]], + vec![], + ); + } + + #[test] + fn test_explicit_inner_join() { + check( + parse( + "SELECT name, license_plate FROM employee INNER JOIN car on employee.id=car.owner_id;", + |p| parse_query(p, false), + ), + expect![[r#" +Root@0..84 + SelectStmt@0..84 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + SelectClause@7..27 + ColumnExpr@7..11 + Expression@7..11 + IdentGroup@7..11 + Ident@7..11 "name" + Comma@11..12 "," + Whitespace@12..13 " " + ColumnExpr@13..27 + IdentGroup@13..26 + Ident@13..26 "license_plate" + Whitespace@26..27 " " + Keyword@27..31 "FROM" + Whitespace@31..32 " " + IdentGroup@32..40 + Ident@32..40 "employee" + Whitespace@40..41 " " + JoinClause@41..83 + InnerJoinClause@41..83 + Keyword@41..46 "INNER" + Whitespace@46..47 " " + Keyword@47..51 "JOIN" + Whitespace@51..52 " " + IdentGroup@52..55 + Ident@52..55 "car" + Whitespace@55..56 " " + Keyword@56..58 "on" + Whitespace@58..59 " " + Expression@59..83 + IdentGroup@59..70 + Ident@59..67 "employee" + Dot@67..68 "." + Ident@68..70 "id" + ComparisonOp@70..71 "=" + IdentGroup@71..83 + Ident@71..74 "car" + Dot@74..75 "." + Ident@75..83 "owner_id" + Semicolon@83..84 ";" +"#]], + vec![], + ); + } + + #[test] + fn test_cross_join() { + check( + parse("SELECT * FROM table1 CROSS JOIN table2;", |p| { + parse_query(p, false) + }), + expect![[r#" +Root@0..39 + SelectStmt@0..39 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + Asterisk@7..8 "*" + Whitespace@8..9 " " + Keyword@9..13 "FROM" + Whitespace@13..14 " " + IdentGroup@14..20 + Ident@14..20 "table1" + Whitespace@20..21 " " + JoinClause@21..38 + CrossJoinClause@21..38 + Keyword@21..26 "CROSS" + Whitespace@26..27 " " + Keyword@27..31 "JOIN" + Whitespace@31..32 " " + IdentGroup@32..38 + Ident@32..38 "table2" + Semicolon@38..39 ";" +"#]], + vec![], + ); + } + #[test] fn test_group_by_having() { check( @@ -1204,6 +1506,401 @@ Root@0..174 IdentGroup@165..173 Ident@165..173 "category" Semicolon@173..174 ";" +"#]], vec![]); + } + + #[test] + fn test_natural_inner_join() { + check( + parse("SELECT * FROM table1 NATURAL JOIN table2;", |p| { + parse_query(p, false) + }), + expect![[r#" +Root@0..41 + SelectStmt@0..41 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + Asterisk@7..8 "*" + Whitespace@8..9 " " + Keyword@9..13 "FROM" + Whitespace@13..14 " " + IdentGroup@14..20 + Ident@14..20 "table1" + Whitespace@20..21 " " + JoinClause@21..40 + NaturalJoinClause@21..40 + Keyword@21..28 "NATURAL" + Whitespace@28..29 " " + Keyword@29..33 "JOIN" + Whitespace@33..34 " " + IdentGroup@34..40 + Ident@34..40 "table2" + Semicolon@40..41 ";" +"#]], + vec![], + ); + } + + #[test] + fn test_outer_join() { + check( + parse( + "SELECT order_id, status, first_name, last_name FROM orders +LEFT JOIN employees ON employee_id = salesman_id ORDER BY order_date DESC;", + |p| parse_query(p, false), + ), + expect![[r#" +Root@0..133 + SelectStmt@0..133 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + SelectClause@7..47 + ColumnExpr@7..15 + Expression@7..15 + IdentGroup@7..15 + Ident@7..15 "order_id" + Comma@15..16 "," + Whitespace@16..17 " " + ColumnExpr@17..23 + Expression@17..23 + IdentGroup@17..23 + Ident@17..23 "status" + Comma@23..24 "," + Whitespace@24..25 " " + ColumnExpr@25..35 + Expression@25..35 + IdentGroup@25..35 + Ident@25..35 "first_name" + Comma@35..36 "," + Whitespace@36..37 " " + ColumnExpr@37..47 + IdentGroup@37..46 + Ident@37..46 "last_name" + Whitespace@46..47 " " + Keyword@47..51 "FROM" + Whitespace@51..52 " " + IdentGroup@52..58 + Ident@52..58 "orders" + Whitespace@58..59 "\n" + JoinClause@59..108 + OuterJoinClause@59..108 + Keyword@59..63 "LEFT" + Whitespace@63..64 " " + Keyword@64..68 "JOIN" + Whitespace@68..69 " " + IdentGroup@69..78 + Ident@69..78 "employees" + Whitespace@78..79 " " + Keyword@79..81 "ON" + Whitespace@81..82 " " + Expression@82..108 + IdentGroup@82..93 + Ident@82..93 "employee_id" + Whitespace@93..94 " " + ComparisonOp@94..95 "=" + Whitespace@95..96 " " + IdentGroup@96..107 + Ident@96..107 "salesman_id" + Whitespace@107..108 " " + OrderByClause@108..132 + Keyword@108..113 "ORDER" + Whitespace@113..114 " " + Keyword@114..116 "BY" + Whitespace@116..117 " " + IdentGroup@117..127 + Ident@117..127 "order_date" + Whitespace@127..128 " " + Keyword@128..132 "DESC" + Semicolon@132..133 ";" +"#]], + vec![], + ); + } + + #[test] + fn test_right_join() { + check( + parse( + "SELECT first_name, last_name, order_id, status FROM orders RIGHT JOIN +employees ON employee_id = salesman_id WHERE job_title = 'Sales Representative' +ORDER BY first_name, last_name;", + |p| parse_query(p, false), + ), + expect![[r#" +Root@0..183 + SelectStmt@0..183 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + SelectClause@7..47 + ColumnExpr@7..17 + Expression@7..17 + IdentGroup@7..17 + Ident@7..17 "first_name" + Comma@17..18 "," + Whitespace@18..19 " " + ColumnExpr@19..28 + Expression@19..28 + IdentGroup@19..28 + Ident@19..28 "last_name" + Comma@28..29 "," + Whitespace@29..30 " " + ColumnExpr@30..38 + Expression@30..38 + IdentGroup@30..38 + Ident@30..38 "order_id" + Comma@38..39 "," + Whitespace@39..40 " " + ColumnExpr@40..47 + IdentGroup@40..46 + Ident@40..46 "status" + Whitespace@46..47 " " + Keyword@47..51 "FROM" + Whitespace@51..52 " " + IdentGroup@52..58 + Ident@52..58 "orders" + Whitespace@58..59 " " + JoinClause@59..110 + OuterJoinClause@59..110 + Keyword@59..64 "RIGHT" + Whitespace@64..65 " " + Keyword@65..69 "JOIN" + Whitespace@69..71 " \n" + IdentGroup@71..80 + Ident@71..80 "employees" + Whitespace@80..81 " " + Keyword@81..83 "ON" + Whitespace@83..84 " " + Expression@84..110 + IdentGroup@84..95 + Ident@84..95 "employee_id" + Whitespace@95..96 " " + ComparisonOp@96..97 "=" + Whitespace@97..98 " " + IdentGroup@98..109 + Ident@98..109 "salesman_id" + Whitespace@109..110 " " + WhereClause@110..152 + Keyword@110..115 "WHERE" + Whitespace@115..116 " " + Expression@116..152 + IdentGroup@116..125 + Ident@116..125 "job_title" + Whitespace@125..126 " " + ComparisonOp@126..127 "=" + Whitespace@127..128 " " + QuotedLiteral@128..150 "'Sales Representative'" + Whitespace@150..152 " \n" + OrderByClause@152..182 + Keyword@152..157 "ORDER" + Whitespace@157..158 " " + Keyword@158..160 "BY" + Whitespace@160..161 " " + Expression@161..171 + IdentGroup@161..171 + Ident@161..171 "first_name" + Comma@171..172 "," + Whitespace@172..173 " " + Expression@173..182 + IdentGroup@173..182 + Ident@173..182 "last_name" + Semicolon@182..183 ";" +"#]], + vec![], + ); + } + + #[test] + fn test_full_outer_join() { + check( + parse( + "SELECT member_name, project_name FROM members FULL OUTER JOIN projects +ON projects.project_id = members.project_id ORDER BY member_name;", + |p| parse_query(p, false), + ), + expect![[r#" +Root@0..137 + SelectStmt@0..137 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + SelectClause@7..33 + ColumnExpr@7..18 + Expression@7..18 + IdentGroup@7..18 + Ident@7..18 "member_name" + Comma@18..19 "," + Whitespace@19..20 " " + ColumnExpr@20..33 + IdentGroup@20..32 + Ident@20..32 "project_name" + Whitespace@32..33 " " + Keyword@33..37 "FROM" + Whitespace@37..38 " " + IdentGroup@38..45 + Ident@38..45 "members" + Whitespace@45..46 " " + JoinClause@46..116 + OuterJoinClause@46..116 + Keyword@46..50 "FULL" + Whitespace@50..51 " " + Keyword@51..56 "OUTER" + Whitespace@56..57 " " + Keyword@57..61 "JOIN" + Whitespace@61..62 " " + IdentGroup@62..70 + Ident@62..70 "projects" + Whitespace@70..72 " \n" + Keyword@72..74 "ON" + Whitespace@74..75 " " + Expression@75..116 + IdentGroup@75..94 + Ident@75..83 "projects" + Dot@83..84 "." + Ident@84..94 "project_id" + Whitespace@94..95 " " + ComparisonOp@95..96 "=" + Whitespace@96..97 " " + IdentGroup@97..115 + Ident@97..104 "members" + Dot@104..105 "." + Ident@105..115 "project_id" + Whitespace@115..116 " " + OrderByClause@116..136 + Keyword@116..121 "ORDER" + Whitespace@121..122 " " + Keyword@122..124 "BY" + Whitespace@124..125 " " + Expression@125..136 + IdentGroup@125..136 + Ident@125..136 "member_name" + Semicolon@136..137 ";" +"#]], + vec![], + ); + } + + #[test] + fn test_cross_apply() { + check( + parse("SELECT * FROM table1 CROSS APPLY table2;", |p| { + parse_query(p, false) + }), + expect![[r#" +Root@0..40 + SelectStmt@0..40 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + Asterisk@7..8 "*" + Whitespace@8..9 " " + Keyword@9..13 "FROM" + Whitespace@13..14 " " + IdentGroup@14..20 + Ident@14..20 "table1" + Whitespace@20..21 " " + JoinClause@21..39 + CrossOuterApplyClause@21..39 + Keyword@21..26 "CROSS" + Whitespace@26..27 " " + Keyword@27..32 "APPLY" + Whitespace@32..33 " " + IdentGroup@33..39 + Ident@33..39 "table2" + Semicolon@39..40 ";" +"#]], + vec![], + ); + } + + #[test] + fn test_outer_apply() { + check( + parse("SELECT * FROM table1 OUTER APPLY table2;", |p| { + parse_query(p, false) + }), + expect![[r#" +Root@0..40 + SelectStmt@0..40 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + Asterisk@7..8 "*" + Whitespace@8..9 " " + Keyword@9..13 "FROM" + Whitespace@13..14 " " + IdentGroup@14..20 + Ident@14..20 "table1" + Whitespace@20..21 " " + JoinClause@21..39 + CrossOuterApplyClause@21..39 + Keyword@21..26 "OUTER" + Whitespace@26..27 " " + Keyword@27..32 "APPLY" + Whitespace@32..33 " " + IdentGroup@33..39 + Ident@33..39 "table2" + Semicolon@39..40 ";" +"#]], + vec![], + ); + } + + #[test] + fn test_multi_join() { + check( + parse( + "SELECT * FROM a JOIN b ON a.id=b.id JOIN c ON c.id=a.id;", + |p| parse_query(p, false), + ), + expect![[r#" +Root@0..56 + SelectStmt@0..56 + Keyword@0..6 "SELECT" + Whitespace@6..7 " " + Asterisk@7..8 "*" + Whitespace@8..9 " " + Keyword@9..13 "FROM" + Whitespace@13..14 " " + IdentGroup@14..15 + Ident@14..15 "a" + Whitespace@15..16 " " + JoinClause@16..36 + InnerJoinClause@16..36 + Keyword@16..20 "JOIN" + Whitespace@20..21 " " + IdentGroup@21..22 + Ident@21..22 "b" + Whitespace@22..23 " " + Keyword@23..25 "ON" + Whitespace@25..26 " " + Expression@26..36 + IdentGroup@26..30 + Ident@26..27 "a" + Dot@27..28 "." + Ident@28..30 "id" + ComparisonOp@30..31 "=" + IdentGroup@31..35 + Ident@31..32 "b" + Dot@32..33 "." + Ident@33..35 "id" + Whitespace@35..36 " " + JoinClause@36..55 + InnerJoinClause@36..55 + Keyword@36..40 "JOIN" + Whitespace@40..41 " " + IdentGroup@41..42 + Ident@41..42 "c" + Whitespace@42..43 " " + Keyword@43..45 "ON" + Whitespace@45..46 " " + Expression@46..55 + IdentGroup@46..50 + Ident@46..47 "c" + Dot@47..48 "." + Ident@48..50 "id" + ComparisonOp@50..51 "=" + IdentGroup@51..55 + Ident@51..52 "a" + Dot@52..53 "." + Ident@53..55 "id" + Semicolon@55..56 ";" "#]], vec![], );