001package gudusoft.gsqlparser.ir.semantic.joinanalysis; 002 003/** 004 * How a {@link JoinEntity} was written in the source SQL. This provenance is 005 * independent of the semantic {@link JoinEntity#getJoinType() join type} and 006 * determines how {@link JoinEntity#getConditionText()} should be interpreted. 007 * 008 * <ul> 009 * <li>{@link #EXPLICIT} — a keyword join ({@code JOIN ... ON}, 010 * {@code LEFT JOIN}, {@code CROSS JOIN}, {@code NATURAL JOIN}, 011 * {@code USING (...)}). Only an anchored {@code ON} expression supplies 012 * non-null condition text; {@code USING}, {@code NATURAL}, and 013 * condition-less keyword joins do not. An explicit lateral join with 014 * {@code ON} remains {@code EXPLICIT} and uses 015 * {@link JoinEntity#isLateral()} as the orthogonal lateral marker.</li> 016 * <li>{@link #COMMA} — a comma-FROM cross product 017 * ({@code FROM a, b}). Condition text is always null, including after 018 * {@code WHERE} predicates promote the semantic join type and populate 019 * {@link JoinEntity#getConditions()}.</li> 020 * <li>{@link #LATERAL} — a lateral join: SQL Server 021 * {@code CROSS APPLY} / {@code OUTER APPLY} (and reserved for 022 * ANSI {@code LATERAL} / PostgreSQL lateral). The right operand 023 * is correlated to the left; the join carries no ON/USING (the 024 * correlation lives inside the right operand), so condition text is 025 * null. Pair with {@link JoinEntity#isLateral()}.</li> 026 * <li>{@link #SEMI} — a predicate-derived semi-join: an 027 * {@code EXISTS} / {@code IN} (or {@code NOT EXISTS} / 028 * {@code NOT IN}) subquery in a WHERE clause (R8), not a written 029 * FROM-clause join. Condition text is the complete verbatim predicate 030 * wrapper when it can be anchored. Pair with 031 * {@link SemanticJoinType#SEMI} / 032 * {@link SemanticJoinType#ANTI_SEMI}.</li> 033 * </ul> 034 * 035 * <p>Introduced by join-analysis slice 162 (S1). 036 */ 037public enum JoinSourceSyntax { 038 EXPLICIT, 039 COMMA, 040 LATERAL, 041 SEMI 042}