public final class LineageNodeKey extends Object
(parent display name, column display
name). Duplicate output names are legal SQL: SELECT a AS [x], b AS x on SQL
Server has two projection slots, two distinct source dependencies — and one published
name. Keying by name therefore conflates them, which is why
ResultColumn today lowercases its alias and appends a (1) suffix to break
the tie. That workaround mutates a published name to carry identity.
Note what is not the fix: making the name key case-sensitive. The two aliases
[x] and x are genuinely the same identifier under SQL Server's rules, so
a correct case-sensitive key still merges them. The slots are distinct for a structural
reason — they are different positions in the projection — so identity must be structural.
Table, ResultSet, TableColumn,
ResultColumn) takes its id from one shared counter,
ModelBindingManager.get().TABLE_COLUMN_ID, and none of them exposes a setter, so
within one analysis an id is unique across kinds and immutable. A column id alone is
therefore already unique; the parent id is carried as well so an index can bucket by
container.
No value is treated as "unassigned". The counter starts from
Option.getStartId(), which callers may set to zero or a negative number — with
startId = -100 the published ids really are negative — so there is no sentinel this
class could reject. That is also why the factories take model objects wherever possible:
deriving both ids from one object is what prevents a mismatched pair, since no validation
can.
Do not build this from the serialized model. The XML/JSON DTOs
(dataflow.model.xml.table and friends) carry String ids that are
renumbered at output time (see DataFlowAnalyzer's table-merge pass), so
they are a presentation concern and are not stable identity.
There are therefore TWO identity domains and this type covers only the first:
long ids from one shared
counter. This class.String parent_id and
column id. Walkers that run on the serialized model, such as
RoutineSummaryExtractor, live there and cannot use this type. They need
SerializedNodeKey, whose whole point is that it keys on the column ID and
never on the column NAME.| Modifier and Type | Method and Description |
|---|---|
boolean |
equals(Object o) |
long |
getColumnId() |
long |
getParentId() |
int |
hashCode() |
static LineageNodeKey |
of(ResultColumn column)
Key for a result-set projection slot.
|
static LineageNodeKey |
of(ResultSetRelationRows rows)
Key for a
RelationRows pseudo-node — whole-row flow through a result set. |
static LineageNodeKey |
of(TableColumn column)
Key for a column of a table endpoint.
|
static LineageNodeKey |
of(TableRelationRows rows)
Key for a table's
RelationRows pseudo-node. |
String |
toString() |
public static LineageNodeKey of(ResultColumn column)
IllegalArgumentException - if the column is null or has no result setpublic static LineageNodeKey of(TableColumn column)
IllegalArgumentException - if the column is null or has no tablepublic static LineageNodeKey of(ResultSetRelationRows rows)
RelationRows pseudo-node — whole-row flow through a result set. It is a
real graph node with its own id from the same counter, so it needs a node key; the text
label "RelationRows" is a different thing and belongs to ModelLabelKey.public static LineageNodeKey of(TableRelationRows rows)
RelationRows pseudo-node.public long getParentId()
public long getColumnId()