001package gudusoft.gsqlparser.sqlenv;
002
003/**
004 * The structural role one component of a qualified SQL name plays — stage S0R of
005 * docs/refactor/identifier_identity_display_separation_plan.md.
006 *
007 * <h3>Why roles must be supplied, never inferred</h3>
008 * A dotted name does not reveal its own shape. {@code customer.name} is {@code table.column} on
009 * most dialects and, on BigQuery, is just as likely to be base column {@code customer} plus STRUCT
010 * field {@code name} — and the two read the first component under DIFFERENT case rules, because
011 * BigQuery table names are case-sensitive while column names are not. Inferring the layout from
012 * the number of components therefore produces a confident wrong answer, which is exactly what the
013 * five existing arity-based planners in this repository do:
014 *
015 * <ul>
016 *   <li>{@code SQLUtil.compareIdentifier}</li>
017 *   <li>{@code IdentifierService.normalizeQualifiedName}</li>
018 *   <li>{@code CatalogIdentifierPolicy.kindForSegment}</li>
019 *   <li>{@code CatalogRuntime.expandCandidates}</li>
020 *   <li>{@code QualifiedNameHierarchy}, which this model replaces and which is deleted at the
021 *       end of this stage, once the key types that supersede it exist</li>
022 * </ul>
023 *
024 * <h3>Where a role legitimately comes from</h3>
025 * The AST is the authority on <em>spelling and component boundaries</em>; it is NOT the authority
026 * on roles. {@code TObjectName.getTableString()} returns the qualifier the user wrote, which may
027 * be an alias rather than a table, and {@code TObjectName.columnToProperty()} physically SHIFTS
028 * the tokens once the parser decides a name is {@code column.property}. So token position is
029 * syntactic and mutable. A role is established by one of:
030 *
031 * <ul>
032 *   <li>resolution, which knows whether a qualifier was an alias or a relation;</li>
033 *   <li>a metadata importer, which already holds catalog / schema / object / column as separate
034 *       fields and should pass them separately rather than joining and re-splitting them;</li>
035 *   <li>a caller that states an explicit layout for a flat string it cannot avoid.</li>
036 * </ul>
037 *
038 * <h3>Not in this enum, on purpose</h3>
039 * Entity kinds — table, view, package, procedure, index — are {@code CatalogObjectKind} values
040 * carried ALONGSIDE an {@link #OBJECT} component, not roles of their own (named in prose, not
041 * linked: this package must not depend on the catalog layer): {@code schema.package.procedure} is two
042 * OBJECT components with different kinds, and folding kinds into roles would multiply this enum
043 * by the catalog's entity list. A routine parameter is a single-segment name scoped by its
044 * routine and keeps using {@code CanonKey(dotParameter)} in a routine-local map.
045 *
046 * <p>There is deliberately no generic {@code FIELD} role either: a STRUCT attribute follows
047 * identifier rules while a JSON/VARIANT key is exact data, and one role could not express both.
048 * {@link #STRUCT_FIELD} covers the identifier-like case; document keys are a different component
049 * type entirely and live in the column-path key, not here.
050 */
051public enum IdentifierComponentRole {
052
053    /** A linked server, e.g. the first component of SQL Server's {@code srv.db.dbo.t}. */
054    SERVER,
055
056    /** A catalog / database. */
057    CATALOG,
058
059    /** A schema. */
060    SCHEMA,
061
062    /**
063     * A named catalog object. The component also carries a {@code CatalogObjectKind}, which is
064     * what distinguishes a table from a view, a package from a procedure, or an index from the
065     * table it sits on — and which is why {@link IdentifierRolePolicy} refuses to map this role:
066     * only a catalog caller knows the kind.
067     */
068    OBJECT,
069
070    /** The column itself — the base of any field path that follows it. */
071    BASE_COLUMN,
072
073    /**
074     * A field of a structured type whose name follows the dialect's IDENTIFIER rules — a BigQuery
075     * STRUCT attribute, a PostgreSQL composite attribute. A document key is NOT this: see the
076     * column-path key's component kinds.
077     */
078    STRUCT_FIELD,
079
080    /**
081     * An Oracle-style database link. It is a postfix qualifier rather than a position in the
082     * dotted hierarchy, so it is stored separately from the ordered component list even though it
083     * participates in equality.
084     */
085    DATABASE_LINK
086}