From 5c953c56b7c95796e72507d0b5e241652ac9714c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?griff=20=D1=96=E2=8A=99?= <346896+griffio@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:00:30 +0000 Subject: [PATCH] Update JoinClauseMixin to support more ANSI SQL joins (#616) * Update JoinClauseMixin Add Ansi join operators RIGHT and FULL Also LATERAL modifier These are added as forward declarations in the SqlLexer.flex that are needed for dialects to override Keep core grammar with LEFT join This allows the existing dialects to work with LEFT join and enables dialects to add RIGHT, FULL where supported, e.g PostgreSql and latest Sqlite dialect * Remove LATERAL LATERAL keyword is used as table/subquery and join operation. Needs special handling --- .../com/alecstrong/sql/psi/core/SqlLexer.flex | 2 ++ .../sql/psi/core/psi/mixins/JoinClauseMixin.kt | 17 +++++++++++++---- .../kotlin/com/alecstrong/sql/psi/core/sql.bnf | 7 ++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/core/src/main/kotlin/com/alecstrong/sql/psi/core/SqlLexer.flex b/core/src/main/kotlin/com/alecstrong/sql/psi/core/SqlLexer.flex index 476b074b..01cbfbd9 100644 --- a/core/src/main/kotlin/com/alecstrong/sql/psi/core/SqlLexer.flex +++ b/core/src/main/kotlin/com/alecstrong/sql/psi/core/SqlLexer.flex @@ -185,6 +185,8 @@ STRING=('([^'])*'|\"([^\"])*\") "INDEXED" { return INDEXED; } "NATURAL" { return NATURAL; } "LEFT" { return LEFT; } + "RIGHT" { return RIGHT; } + "FULL" { return FULL; } "OUTER" { return OUTER; } "INNER" { return INNER; } "CROSS" { return CROSS; } diff --git a/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/JoinClauseMixin.kt b/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/JoinClauseMixin.kt index edf9fcca..b6a0241c 100644 --- a/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/JoinClauseMixin.kt +++ b/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/JoinClauseMixin.kt @@ -5,10 +5,12 @@ import com.alecstrong.sql.psi.core.psi.QueryElement.QueryResult import com.alecstrong.sql.psi.core.psi.SqlCompositeElementImpl import com.alecstrong.sql.psi.core.psi.SqlJoinClause import com.alecstrong.sql.psi.core.psi.SqlJoinConstraint +import com.alecstrong.sql.psi.core.psi.SqlJoinOperator import com.alecstrong.sql.psi.core.psi.SqlTypes import com.intellij.lang.ASTNode import com.intellij.psi.PsiElement import com.intellij.psi.PsiNamedElement +import com.intellij.psi.tree.TokenSet internal abstract class JoinClauseMixin( node: ASTNode, @@ -61,10 +63,7 @@ internal abstract class JoinClauseMixin( var columns = query.flatMap { it.columns } var synthesizedColumns = query.flatMap { it.synthesizedColumns } - if (operator.node.findChildByType( - SqlTypes.LEFT, - ) != null - ) { + if (supportsJoinOperator(operator)) { columns = columns.map { it.copy(nullable = true) } synthesizedColumns = synthesizedColumns.map { it.copy(nullable = true) } } @@ -90,5 +89,15 @@ internal abstract class JoinClauseMixin( return@ModifiableFileLazy queryAvailable } + private fun supportsJoinOperator(operator: SqlJoinOperator): Boolean { + return operator.node.findChildByType( + TokenSet.create( + SqlTypes.LEFT_JOIN_OPERATOR, + SqlTypes.RIGHT_JOIN_OPERATOR, + SqlTypes.FULL_JOIN_OPERATOR, + ), + ) != null + } + override fun queryExposed() = queryExposed.forFile(containingFile) } diff --git a/core/src/main/kotlin/com/alecstrong/sql/psi/core/sql.bnf b/core/src/main/kotlin/com/alecstrong/sql/psi/core/sql.bnf index df999d13..b798784d 100644 --- a/core/src/main/kotlin/com/alecstrong/sql/psi/core/sql.bnf +++ b/core/src/main/kotlin/com/alecstrong/sql/psi/core/sql.bnf @@ -383,8 +383,13 @@ result_column ::= ( MULTIPLY "com.alecstrong.sql.psi.core.psi.SqlCompositeElement" ] } + +left_join_operator ::= LEFT +right_join_operator ::= RIGHT +full_join_operator ::= FULL + join_operator ::= ( COMMA - | [ NATURAL ] [ LEFT [ OUTER ] | INNER | CROSS ] JOIN ) + | [ NATURAL ] [ left_join_operator [ OUTER ] | INNER | CROSS ] JOIN ) join_constraint ::= [ ON expr | USING LP column_name ( COMMA column_name ) * RP ] ordering_term ::= expr [ COLLATE collation_name ] [ ASC | DESC ] { mixin = "com.alecstrong.sql.psi.core.psi.mixins.OrderByMixin"