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}