public final class NormalNameCollisions extends Object
Lineage keys its models by SQLUtil#normalizeIdentifier, and the legacy fold behind it
can give two different names one string: PostgreSQL "Amount" and amount both
become AMOUNT, ClickHouse userId and userid both become USERID.
Lineage then treats the two as one column, and every reference to either picks up both as its
source. The same string is also displayed in places, so it cannot change for every name.
So before the first statement is analyzed, scan(gudusoft.gsqlparser.EDbVendor, java.util.Collection<java.lang.String>) reads every identifier token of the
analysis's SQL and finds the legacy strings that more than one identity shares. Only a name whose
legacy string is contested changes (normalName(java.util.Set<java.lang.String>, gudusoft.gsqlparser.EDbVendor, gudusoft.gsqlparser.sqlenv.ESQLDataObjectType, java.lang.String, java.lang.String)): it keeps the legacy string when that
string, read back as SQL, denotes it (amount keeps AMOUNT on PostgreSQL), and
otherwise gets a spelling that denotes it ("Amount"). Lineage compares these strings as
SQL names, so each one must name its own identity; the first name to arrive keeping the legacy
string would not, because AMOUNT read back as SQL is amount whoever holds it.
Column names are contested without case, because lineage matches column normal names
case-insensitively even where the legacy fold keeps case (Oracle, whose quoted "Amount"
gives Amount next to a bare amount's AMOUNT). Names are told apart under
the analysis's own rules, so a configured profile's stricter ones count.
The result is a pure function of the contested set, so all spellings of a legacy string change together. A name the scan did not see (dynamic SQL, a name only metadata holds) follows the same rule: it changes if its string is contested, and otherwise keeps the merge the legacy fold always made. No string is ever split for some of its names and merged for the rest.
| Modifier and Type | Method and Description |
|---|---|
static String |
contestedKey(IdentifierService service,
ESQLDataObjectType type,
String legacy)
The contested key of the legacy name
legacy of a name of role type, as scan(gudusoft.gsqlparser.EDbVendor, java.util.Collection<java.lang.String>) returns
them: for a caller that finds two names sharing one legacy name outside the SQL text a scan reads. |
static Set<String> |
legacyNames(Set<String> contested)
The legacy strings of
contested, whatever their class and upper-cased: a cheap first
test, which normalName(java.util.Set<java.lang.String>, gudusoft.gsqlparser.EDbVendor, gudusoft.gsqlparser.sqlenv.ESQLDataObjectType, java.lang.String, java.lang.String) then makes exact. |
static String |
normalName(Set<String> contested,
EDbVendor vendor,
ESQLDataObjectType type,
String origin,
String legacy)
The normal name of one identifier segment, given the contested keys of its analysis.
|
static String |
normalName(Set<String> contested,
IdentifierService service,
ESQLDataObjectType type,
String origin,
String legacy)
normalName(Set, EDbVendor, ESQLDataObjectType, String, String) under the analysis's
own identifier rules; pass the service scan(IdentifierService, Collection) used. |
static Set<String> |
scan(EDbVendor vendor,
Collection<String> sqlTexts)
The legacy normal names that two different identities share in
sqlTexts, keyed for
normalName(java.util.Set<java.lang.String>, gudusoft.gsqlparser.EDbVendor, gudusoft.gsqlparser.sqlenv.ESQLDataObjectType, java.lang.String, java.lang.String). |
static Set<String> |
scan(IdentifierService service,
Collection<String> sqlTexts)
scan(EDbVendor, Collection) under the analysis's own identifier rules, which a
configured profile may make stricter than the vendor's (SQL Server under a case-sensitive
collation tells Amount from AMOUNT). |
static Set<String> |
scanTokens(IdentifierService service,
Collection<TSourceTokenList> tokenLists)
scan(gudusoft.gsqlparser.EDbVendor, java.util.Collection<java.lang.String>) over tokens already read, such as a parser's token list after it parsed the
analysis's only unit, which spares lexing the text a second time. |
public static Set<String> scan(EDbVendor vendor, Collection<String> sqlTexts)
sqlTexts, keyed for
normalName(java.util.Set<java.lang.String>, gudusoft.gsqlparser.EDbVendor, gudusoft.gsqlparser.sqlenv.ESQLDataObjectType, java.lang.String, java.lang.String). Empty when no two names collide, which is the common case.vendor - the analysis's vendor; names are compared under its default identifier rules
(see scan(IdentifierService, Collection) for a configured profile)sqlTexts - every unit of SQL the analysis will readpublic static Set<String> scan(IdentifierService service, Collection<String> sqlTexts)
scan(EDbVendor, Collection) under the analysis's own identifier rules, which a
configured profile may make stricter than the vendor's (SQL Server under a case-sensitive
collation tells Amount from AMOUNT).public static Set<String> scanTokens(IdentifierService service, Collection<TSourceTokenList> tokenLists)
scan(gudusoft.gsqlparser.EDbVendor, java.util.Collection<java.lang.String>) over tokens already read, such as a parser's token list after it parsed the
analysis's only unit, which spares lexing the text a second time.public static Set<String> legacyNames(Set<String> contested)
contested, whatever their class and upper-cased: a cheap first
test, which normalName(java.util.Set<java.lang.String>, gudusoft.gsqlparser.EDbVendor, gudusoft.gsqlparser.sqlenv.ESQLDataObjectType, java.lang.String, java.lang.String) then makes exact.public static String normalName(Set<String> contested, EDbVendor vendor, ESQLDataObjectType type, String origin, String legacy)
contested - keys from scan(gudusoft.gsqlparser.EDbVendor, java.util.Collection<java.lang.String>)vendor - vendor the legacy name was folded fortype - role of the segmentorigin - the segment as writtenlegacy - its legacy normal namelegacy, unless another name shares it and it does not denote originpublic static String normalName(Set<String> contested, IdentifierService service, ESQLDataObjectType type, String origin, String legacy)
normalName(Set, EDbVendor, ESQLDataObjectType, String, String) under the analysis's
own identifier rules; pass the service scan(IdentifierService, Collection) used.public static String contestedKey(IdentifierService service, ESQLDataObjectType type, String legacy)
legacy of a name of role type, as scan(gudusoft.gsqlparser.EDbVendor, java.util.Collection<java.lang.String>) returns
them: for a caller that finds two names sharing one legacy name outside the SQL text a scan reads.