Data lineage options, explained¶
DataFlowAnalyzer is the class that answers one question about a SQL script:
For every column that gets written, which source columns did its value come from — through which joins, functions, CTEs, temp tables, procedures and dynamic SQL?
The answer is a graph. Option is the object that decides how much of that graph
you get back and how it is labelled. This page walks through every setting on
Option, one at a time, with a small SQL statement and the actual output GSP
produces with the setting off and on.
Who this page is for
You are new to data lineage, or new to GSP, and you want to know what each option means before you switch it on. If you already know the option you need and just want its CLI flag or its availability in the SQLFlow web UI, use Configuration options instead — that page is organised by delivery mode (Query / Job / CLI / API); this one is organised by what the option does to the lineage graph.
Verified against
| GSP Java version | 4.2.8 (TBaseType.versionid), released 2026-08-31 |
| Page last verified | 2026-09-08 |
| Options covered | 70 mutators on Option |
Every SQL sample and every block of output below was produced by running that build — none of it is written by hand. The stamp records what was true for 4.2.8. A newer GSP release does not silently invalidate the page, but the stamp, not the release notes, is what tells you how far behind it might be. See Refreshing this page for how to bring it forward.
1. Before the options: one run, one output¶
1.1 Your first analysis¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
The same analysis from the command line:
1 2 | |
1.2 Reading the output¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
Six ideas explain that document, and once you have them, every option below is easy:
| Element | What it is |
|---|---|
<table> |
A real database object the SQL touched — orders, customers, order_report. |
<resultset> |
An intermediate step invented by the query: the SELECT list feeding an INSERT (INSERT-SELECT-1), a CTE, a subquery, a function call. Names like RS-1 are display labels, not object names. |
<relationship type="fdd"> |
Direct lineage. "The value of the target column is built from these source columns." This is what most people mean by column lineage. |
<relationship type="fdr"> |
Indirect lineage. "This source column decided which rows arrived, but its value never became the target value." Join keys, WHERE predicates, GROUP BY keys. |
RelationRows |
A synthetic column standing for "the rows of this relation". fdr edges point at it, which keeps row-influence out of your value-level graph. |
coordinate |
[line,column,offset] start and end in the source text, so you can highlight the exact SQL that produced an edge. |
Read the graph by following fdd edges backwards from a target:
1 2 | |
Do not parse this XML in your application
generateDataFlow() returns the serialized XML for humans and for pipes. In Java,
call analyzer.getDataFlow() and walk the object model instead — see
§12.1.
1.3 Setting options¶
Every option lives on one Option object that you hand to the constructor:
1 2 3 4 5 6 7 | |
DataFlowAnalyzer mirrors a handful of the same setters
(setShowJoin, setIgnoreRecordSet, setSimpleShowFunction, …) and forwards them
to the Option it holds, so analyzer.setShowJoin(true) and
option.setShowJoin(true) do the same thing. Prefer configuring Option: it holds
the full set.
2. Option cheat sheet¶
Jump straight to the option you need. Default is the value you get if you never touch it.
Dialect, names and qualification¶
| Option | Default | One line |
|---|---|---|
setVendor |
(unset) | Which SQL dialect to parse. Set it. |
setDefaultServer / setDefaultDatabase / setDefaultSchema |
(unset) | Qualify unqualified table names with the session's server/database/schema. |
setShowImplicitSchema |
false |
Keep the filled-in qualifiers visible in the output. |
setNormalizeOutput |
false |
Fold every name to the dialect's canonical case. |
setFilePathDatabase / setFilePathSchema |
(unset) | Qualify file/stage/URI objects (s3://…) the same way. |
setPowerQueryInnerVendor |
(unset) | Dialect of the SQL embedded inside Power Query Value.NativeQuery(). |
setEnableMssqlColonBindVariables |
false |
Let the SQL Server parser accept :name bind variables. |
Shape and detail of the output¶
| Option | Default | One line |
|---|---|---|
setSimpleOutput |
false |
Collapse every intermediate step; report only table → table. |
setTextFormat |
false |
Print x depends on: t.y lines instead of XML (simple output only). |
setOutput |
true |
false skips XML serialization; consume getDataFlow() instead. |
setIgnoreCoordinate |
false |
Drop all coordinate attributes. |
setTraceTablePosition |
false |
Record every place a table is referenced, not just the first. |
setTransform / setTransformCoordinate |
false |
Attach the expression text (and its position) that transformed each value. |
setStartId |
0 |
Offset all generated ids, so several runs can share one graph. |
setTraceSQL |
false |
Stamp each edge with the hash of the statement that produced it. |
setTraceProcedure |
false |
Stamp each edge with the id of the procedure that produced it. |
What survives simple output¶
| Option | Default | One line |
|---|---|---|
setSimpleShowFunction |
false |
Keep function nodes (COUNT, SUM, UDFs) as visible hops. |
setSimpleShowUdfFunctionOnly |
false |
Keep only user-defined functions as hops; inline the built-ins. |
setSimpleShowVariable |
false |
Keep procedure variables as visible hops. |
setSimpleShowCursor |
false |
Keep cursors as visible hops. |
setSimpleShowSynonym |
false |
Keep synonyms as visible hops. |
setSimpleShowTopSelectResultSet |
false |
Keep the final SELECT list — without it a read-only query yields nothing. |
setSimpleRetainIntermediate |
false |
Keep every intermediate kind at once. |
showResultSetTypes |
(none) | Keep intermediates of named kinds only. |
setSimpleShowRelationTypes |
(none) | Which edge types simple output emits. |
setSqlflowIgnoreFunction |
false |
Force-drop function nodes, overriding the switches above. |
setIgnoreTemporaryTable |
false |
Collapse lineage straight through temp tables. |
Extra relationship kinds¶
| Option | Default | One line |
|---|---|---|
setShowJoin |
false |
Emit type="join" records with join type and condition text. |
setShowCallRelation |
false |
Emit type="call" records for procedure → procedure calls. |
setShowERDiagram |
false |
Emit type="er" records for declared foreign keys. |
setAnalyzeMode |
dataflow |
crud adds type="crud" create/read/update/delete records. |
Precision and noise¶
| Option | Default | One line |
|---|---|---|
setIgnoreRecordSet |
false |
Remove intermediate result sets from the full output too. |
setIgnoreTopSelect |
false |
Drop the final SELECT's result set. |
setShowConstantTable |
false |
Show literals as a synthetic SQL_CONSTANTS-n source. |
setIgnoreInsertIntoValues |
true |
Whether INSERT … VALUES literals count as constants. |
setShowCountTableColumn |
true |
Whether COUNT(x) is a direct dependency on x. |
setShowCaseWhenAsDirect |
true |
Whether a CASE condition column is direct or indirect. |
filterRelationTypes |
(none) | Keep only the listed edge types. |
setIgnoreUnusedSynonym |
true |
Drop synonyms nothing reads from. |
Names GSP cannot resolve¶
| Option | Default | One line |
|---|---|---|
setLinkOrphanColumnToFirstTable |
false |
Guess a home table for an unresolvable column. |
setShowCandidateTable |
true |
List the other tables it might have belonged to. |
Procedures, functions and dynamic SQL¶
| Option | Default | One line |
|---|---|---|
addExcludedProcedureName / addExcludedProcedurePattern |
(none) | Skip named procedures, with * / ? wildcards. |
setEnablePipelinedStitching |
true |
Carry lineage through Oracle pipelined table functions. |
setMaxPipelinedExpansionDepth |
8 |
Nesting bound for that stitching. |
setMaxStitchedSourcesPerColumn |
64 |
Fan-in bound for that stitching. |
setIdentityFirstVariablePools |
false |
Give each routine overload its own variable pool. |
setAnalyzeDynamicSql |
true |
Analyze SQL built as a string and executed. |
setDynamicSqlTrustMode |
LEGACY |
SHADOW also reports how complete each dynamic site was. |
setReportDynamicSqlSitesAsErrors |
false |
Mirror unresolved dynamic sites into the error list. |
setAssumeExternalScriptPassthrough |
true |
Assume a Python/R external script passes columns through positionally. |
Large inputs¶
| Option | Default | One line |
|---|---|---|
setAutoDetectLargeFile |
false |
Delegate oversized inputs to the parallel analyzer instead of risking OOM. |
setParallel |
cores/2 − 1 |
Worker count for parallel analysis. |
| thresholds | see table | What counts as "large". |
Integration hooks¶
| Option | Default | One line |
|---|---|---|
setHandleListener |
(none) | Progress callbacks and cancellation. |
setCollectAuthoritativeLineageEvidence |
false |
Collect the SLPC evidence sidecar. |
3. Dialect, names and qualification¶
setVendor(EDbVendor)¶
Default: unset. The dialect GSP parses with. Everything else depends on getting
this right — #temp tables, EXEC, PIPE ROW, IDENTIFIER() and quoting rules all
differ per vendor. See the
list of supported dialects.
1 | |
On the command line this is /t:
1 | |
setDefaultDatabase(String) · setDefaultSchema(String) · setDefaultServer(String)¶
Default: unset. Real scripts say FROM orders, not
FROM SALESDB.dbo.orders. These three tell GSP what the session defaults were, so
unqualified names resolve to fully-qualified objects — which is what makes lineage
from two different scripts join up in a catalog.
1 | |
1 | |
1 | |
setDefaultSchema is currently ignored (bug #4720)
As of 4.2.8 the value you pass to setDefaultSchema never reaches the output.
Qualification is triggered by the default database, and the schema segment is
always filled from the dialect's own default:
| Options | Reported name |
|---|---|
setDefaultSchema("myschema") only |
orders — no qualification at all |
setDefaultDatabase("SALESDB") only |
SALESDB.dbo.orders |
both, schema myschema |
SALESDB.dbo.orders — your value is discarded |
The example above uses dbo only because that is what SQL Server would have
produced anyway. On Oracle, PostgreSQL, Snowflake and BigQuery the discarded
schema shows up as the placeholder DEFAULT.
Until this is fixed, do not rely on setDefaultSchema to attribute lineage to a
non-default schema — supply real catalog metadata through
setSqlEnv instead, or qualify the
names in the SQL. setDefaultServer likewise only matters for dialects that have
a server layer above the database.
setShowImplicitSchema(boolean)¶
Default: false · CLI /showImplicitSchema. Some objects carry an implicit
qualifier that the resolver worked out from context rather than from the text —
the database a USE statement switched to, the schema that owns a package body,
the catalog recorded in supplied metadata. By default that qualifier is not
printed; this option adopts it as the object's database/schema.
It is distinct from
setDefaultDatabase: that one supplies a session default you
know, this one surfaces one GSP inferred. If no implicit qualifier was inferred —
which is the usual case when you analyze a bare script with no
metadata — the output is unchanged.
setNormalizeOutput(boolean)¶
Default: false. Rewrites every object and column name to the dialect's
canonical case, so orders, Orders and ORDERS in three scripts become one node.
1 | |
1 2 3 4 | |
1 2 3 4 | |
The canonical case is the dialect's: Oracle and Snowflake fold to upper case, MySQL
does not fold at all. Quoted identifiers keep their case, because in these dialects
"Store" and Store are genuinely different columns.
setFilePathDatabase(String) · setFilePathSchema(String)¶
Default: unset. The same idea as setDefaultDatabase, but for objects that are
paths rather than tables — external stages, COPY INTO locations, data-lake URIs.
1 2 3 | |
1 | |
1 | |
setPowerQueryInnerVendor(EDbVendor)¶
Default: unset (inferred). Power Query / M scripts embed native SQL inside
Value.NativeQuery(). By default GSP infers that inner dialect from the connector
in the M code. Set this when the inference is wrong or the connector is unknown.
setEnableMssqlColonBindVariables(boolean)¶
Default: false. SQL Server has no :name bind variables, but many JDBC/ORM
layers hand GSP SQL that still contains them. Without this switch such a script is a
syntax error and you get no lineage at all:
1 2 | |
1 2 3 4 | |
1 2 3 4 | |
4. Shape and detail of the output¶
setSimpleOutput(boolean)¶
Default: false · CLI /s. The single most useful option, and the first one to
try. Full output shows every intermediate hop; simple output collapses them and
reports only real objects to real objects.
1 2 3 4 5 6 7 8 9 10 | |
24 relationships, including RS-1, the COUNT function node, the
INSERT-SELECT node and every fdr row-influence edge. Excerpt:
1 2 3 4 5 6 7 8 | |
Four relationships, no intermediates:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Nothing is lost — the two-hop path employee.emp_id → COUNT → RS-1 → dept_summary.headcount
becomes the single edge employee.emp_id → dept_summary.headcount. Use simple output
to populate a catalog; use full output to explain why an edge exists.
The rest of §5 is about putting selected intermediates back into simple output.
setTextFormat(boolean)¶
Default: false · CLI /text. With simple output, print one plain line per edge
instead of XML. Perfect for a first look, grep, or a smoke test.
1 2 | |
Same script as above:
1 2 3 4 | |
Note
textFormat only applies when simpleOutput is on. The CLI enforces this too:
/text is read only after /s.
setOutput(boolean)¶
Default: true. Set false when your program consumes the object model and
never needs the XML string — the serialization step is skipped and
generateDataFlow() returns null. See
§12.1.
setIgnoreCoordinate(boolean)¶
Default: false · CLI /ic. Removes every coordinate attribute. Use it when
you are diffing two runs, storing output, or reading it by eye — coordinates roughly
double the size of the document.
1 2 3 | |
1 2 3 | |
setTraceTablePosition(boolean)¶
Default: false. A table referenced five times normally reports one position.
Turn this on to record them all — useful for "highlight every mention of this table"
features.
1 2 | |
1 | |
1 | |
setTransform(boolean) · setTransformCoordinate(boolean)¶
Default: false · CLI /transform, /coor. Lineage tells you that a value
flowed; transform tells you what happened to it on the way by attaching the
source text of the expression. transformCoordinate adds that expression's position.
1 2 | |
1 2 3 4 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 | |
setStartId(long)¶
Default: 0. Every node and edge gets a small integer id, restarting at 0 on
each run. If you analyze 50 files separately and merge the results, those ids
collide. Give each run its own range instead.
1 | |
1 2 3 4 5 | |
1 2 3 4 5 | |
setTraceSQL(boolean)¶
Default: false. Stamps every relationship with sqlHash, the hash of the
statement it came from — so you can answer "which statement created this edge?" when
a script has hundreds.
1 | |
1 | |
The same hash appears as queryHashId on the <process> element, so you can join
edges back to statements.
setTraceProcedure(boolean)¶
Default: false. The same idea for routines: every relationship carries the
procedureId of the procedure whose body produced it.
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 | |
1 2 | |
procedureId="1" is load_staging, procedureId="16" is run_etl.
5. What survives simple output¶
Simple output hides all intermediates. Usually that is what you want — but sometimes one kind of intermediate is the whole point of the analysis ("which UDF touched this column?", "which variable carried this value?"). Each option below puts one kind back.
All examples in this section use setSimpleOutput(true) and
setTextFormat(true).
setSimpleShowFunction(boolean)¶
Default: false. Keeps function calls as visible nodes.
1 2 3 4 | |
1 2 3 | |
1 2 3 4 5 | |
setSimpleShowUdfFunctionOnly(boolean)¶
Default: false. Used together with setSimpleShowFunction(true): keep only
user-defined functions as nodes and inline the built-ins. This is usually what
you want for governance — nobody needs COUNT in the graph, but a UDF is a piece of
business logic worth tracking.
1 2 3 4 5 | |
1 2 3 4 | |
COUNT is gone and headcount now depends directly on employee.emp_id; the UDF
fmt_label is still a hop.
setSimpleShowVariable(boolean)¶
Default: false. Procedure variables are normally invisible plumbing. Turn this
on when you need to see which variable carried a value.
1 2 3 4 5 6 7 8 | |
1 | |
1 2 | |
setSimpleShowCursor(boolean)¶
Default: false. The same, for cursors.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 | |
1 2 3 4 | |
1 2 3 4 5 6 | |
setSimpleShowVariable also reveals cursors, because the fetch target is a variable
whose source is the cursor.
setSimpleShowSynonym(boolean)¶
Default: false. Keeps a synonym as its own node instead of resolving straight
through to the base object.
1 2 3 | |
1 | |
1 2 3 | |
setSimpleShowTopSelectResultSet(boolean)¶
Default: false · CLI /topselectlist. Simple output reports lineage into
targets. A plain SELECT writes nothing, so it has no target — and simple output
is empty. This option makes the final SELECT list a target.
1 2 | |
1 | |
(empty — the query persists nothing)
1 2 | |
Tip
If simple output is unexpectedly empty, this is almost always the reason: the script is read-only. Turn this option on, or analyze a script that writes something.
setSimpleRetainIntermediate(boolean)¶
Default: false. The "keep everything interesting" switch: retains function
nodes, variables, cursors and procedure result sets in one go, rather than enabling
four options.
1 2 3 4 5 | |
1 2 | |
1 2 3 | |
showResultSetTypes(String…)¶
Default: none · CLI /showResultSetTypes. Fine-grained version of the options
above: name exactly which kinds of intermediate result set to keep. The value matches
the type attribute on <resultset> in the full output (- and _ are
interchangeable).
1 | |
Accepted names: select_list, array, struct, result_of, cte,
insert_select, update_select, merge_update, merge_insert, output,
update_set, pivot_table, unpivot_table, alias, function, case_when,
cursor, variable.
Using the CTE script above:
1 2 | |
1 2 3 | |
1 2 3 4 5 6 7 | |
cte and result_of do not work yet (bug #4719)
A CTE result set is emitted with type="with_cte", which the cte value does not
match, so asking for cte silently keeps nothing. result_of has no effect either.
To keep CTE nodes today, use
setSimpleRetainIntermediate or full output.
setSimpleShowRelationTypes(String…)¶
Default: none · CLI /simpleShowRelationTypes. Which relationship types simple
output emits. Values: fdd (alias direct), fdr (alias indirect), fddi,
frd, join, call, er, crud.
1 | |
For the INSERT … SELECT … JOIN script of §1:
1 2 | |
1 | |
Use fdr to build an impact/filter graph — "which columns decided which rows
landed in this table" — separately from the value graph.
setSqlflowIgnoreFunction(boolean)¶
Default: false. Force-drops function result sets even when
setSimpleShowFunction(true) would have kept them. It exists so a host application
can veto function nodes globally without rewriting per-request options.
1 2 3 4 5 | |
1 2 3 | |
setIgnoreTemporaryTable(boolean)¶
Default: false · CLI /withTemporaryTable is the opposite. A staging temp
table is real to the engine but noise in a catalog. This option collapses lineage
straight through it.
1 2 3 4 | |
1 2 3 4 | |
1 2 | |
…and in XML the temp table is gone but the path is preserved:
1 2 3 4 | |
Lineage is collapsed, not deleted: order_report.order_id still traces to
orders.order_id.
6. Extra relationship kinds¶
The options in this section do not change existing edges; they add new kinds of record to the same document.
setShowJoin(boolean)¶
Default: false · CLI /j. Emits a dedicated type="join" record per join,
carrying the join type and the condition text. Column lineage tells you values
flowed; this tells you the tables were joined, and on what.
1 2 3 4 | |
1 2 3 4 | |
For richer join semantics see Join analysis.
setShowCallRelation(boolean)¶
Default: false. Emits type="call" records — the
procedure call graph, alongside the data graph.
Using the two-procedure script from setTraceProcedure:
1 2 3 4 | |
Note the different endpoint element names: call records use <caller>/<callee>,
not <target>/<source>.
setShowERDiagram(boolean)¶
Default: false · CLI /showER. Emits type="er" records for foreign keys
declared in DDL — an entity-relationship view of the same script.
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 | |
1 2 3 4 | |
Column metadata (dataType, primaryKey, foreignKey) is reported from the DDL
either way.
setAnalyzeMode(AnalyzeMode)¶
Default: dataflow. Values: dataflow, crud, dynamic. In crud mode GSP
additionally emits type="crud" records describing operations on objects —
useful for "what does this script create/read/update/delete?" rather than "where does
this value come from?".
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 | |
7. Precision and noise¶
setIgnoreRecordSet(boolean)¶
Default: false · CLI /i. Removes intermediate result sets from the full
output, keeping everything else (coordinates, fdr edges, functions). Think of it as
"simple output for result sets only".
1 2 3 4 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 | |
setIgnoreTopSelect(boolean)¶
Default: false. The mirror image of
setSimpleShowTopSelectResultSet: drops the
final SELECT's result set from the full output, so only persisted targets remain.
1 2 3 | |
1 2 3 4 5 6 7 8 9 | |
RS-2 and both of its edges are gone; the SELECT … INTO #tmp_orders lineage
remains.
setShowConstantTable(boolean)¶
Default: false · CLI /showConstant. A column whose value is a literal has no
source column, so by default it gets no lineage at all and simply disappears from the
graph. This option gives literals a home: a synthetic SQL_CONSTANTS-n table.
1 2 | |
1 2 3 4 5 6 7 8 | |
src_system has no incoming edge.
1 2 3 4 5 6 7 8 | |
Turn it on when your consumer needs every target column to have a source, even a constant one.
setIgnoreInsertIntoValues(boolean)¶
Default: true. Decides whether literals in an INSERT … VALUES list count as
constants. It only has a visible effect together with
setShowConstantTable(true).
1 2 | |
1 2 3 | |
Only the function-valued item is kept; the plain literals 1 and 'LOGIN' are
ignored.
1 2 3 4 5 6 7 8 9 | |
setShowCountTableColumn(boolean)¶
Default: true · CLI /treatArgumentsInCountFunctionAsDirectDataflow. COUNT(x)
is philosophically odd: the result does not contain x's value, it counts rows. This
option decides whether x → COUNT is reported as a direct (fdd) dependency.
Using the COUNT(e.emp_id) view script from §4:
1 2 3 4 | |
That fdd edge is gone. The indirect edges remain:
1 2 3 4 | |
Warning
Switching this off removes real edges from your value graph. Only do it if your
downstream consumer treats "counted" as row-influence rather than value-flow — and
then read the fdr edges, or the dependency disappears entirely.
setShowCaseWhenAsDirect(boolean)¶
Default: true · CLI /showCaseWhenAsIndirect is the opposite. In
CASE WHEN status = 'A' THEN amount ELSE 0 END, amount clearly flows into the
result. What about status? It picks which value is returned but its own value
never appears. This option decides how status is classified.
1 2 | |
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 | |
The edge is never dropped — only reclassified from fdd to fdr. Choose false for
a strict value-flow graph, true (the default) if a change to status should show up
as impacting net_amount.
filterRelationTypes(String…)¶
Default: none · CLI /filterRelationTypes. Despite the name, this is a
whitelist: only the listed relationship types are emitted. Same value set as
setSimpleShowRelationTypes, including the direct /
indirect aliases.
1 | |
For the INSERT … SELECT … JOIN script of §1:
1 2 3 4 5 6 | |
1 2 3 4 | |
1 2 | |
setIgnoreUnusedSynonym(boolean)¶
Default: true. When the same object appears under several names, a synonym that
nothing ever reads from is dropped rather than merged into the graph. Set false to
keep every declared synonym node.
8. Names GSP cannot resolve¶
Sometimes a column cannot be attributed to a table: several tables are in scope, none is qualified, and no catalog metadata was supplied. GSP calls these orphan columns and, by default, refuses to guess.
The real fix is metadata
Supplying a TSQLEnv (CLI /env metadata.json) with the real table/column lists
resolves these cases exactly, instead of heuristically. The two options below are for
when metadata is not available.
setLinkOrphanColumnToFirstTable(boolean)¶
Default: false · CLI /lof. Attributes an orphan column to the first table in
the FROM clause, and records that it did so.
1 2 | |
1 2 3 4 5 6 7 8 9 | |
No lineage edge — order_no sits in a pseudoTable and an error records why.
1 2 3 4 5 6 7 8 9 10 | |
This is a guess, and it is labelled as one
order_no may well belong to customers. The edge is emitted so the graph is not
silently incomplete, but the <candidateTables> list and the LinkOrphanColumn
error exist so your consumer can mark it as unproven. Do not present such an edge to
users with the same confidence as a resolved one.
setShowCandidateTable(boolean)¶
Default: true. Whether the <candidateTables> block above is emitted. Set
false only if your consumer cannot handle the nested element.
1 2 3 4 | |
The guess is still recorded in the LinkOrphanColumn error, but the alternatives
are no longer visible.
9. Procedures, functions and dynamic SQL¶
addExcludedProcedureName(String) · addExcludedProcedurePattern(String)¶
Default: none. Skip named routines entirely — logging helpers, audit wrappers,
vendor utilities that add nothing but noise. Patterns support * (any run of
characters) and ? (one character); . separates name segments. Matching is
case-insensitive and quoting (", [], `) is stripped before matching.
1 2 | |
Using the two-procedure script from setTraceProcedure:
1 2 | |
1 | |
load_staging's body is no longer analyzed, so stg_orders ← orders is gone.
setEnablePipelinedStitching(boolean)¶
Default: true. Oracle pipelined table functions are a lineage cliff: the caller
selects from TABLE(get_orders()) and the real source tables are inside the function
body. This option stitches the two sides together. Leave it on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 | |
1 | |
(empty — orders and order_report both appear as tables, with no edge
between them)
setMaxPipelinedExpansionDepth(int)¶
Default: 8. How deeply pipelined functions may be expanded into one another
before GSP stops. A guard against pathological or recursive nesting.
setMaxStitchedSourcesPerColumn(int)¶
Default: 64. Upper bound on how many stitched sources one column may collect,
so a very wide function body cannot explode the graph.
setIdentityFirstVariablePools(boolean)¶
Default: false. Advanced. Gives each routine overload its own pool of
variables instead of merging same-named formal parameters across overloads. Only
relevant to the routine-summary analysis pipelines; leave at the default unless you
are working on those.
setAnalyzeDynamicSql(boolean)¶
Default: true. SQL built as a string and executed (EXEC(@sql),
sp_executesql, EXECUTE IMMEDIATE, DBMS_SQL.PARSE) is analyzed like ordinary SQL
whenever GSP can materialize its text.
1 2 3 4 | |
1 2 3 4 5 6 7 8 | |
1 2 3 4 | |
report_daily, orders and both edges are gone — the procedure appears to touch
nothing.
Turn it off only when you must analyze static SQL exclusively; it removes real, provable lineage.
setDynamicSqlTrustMode(DynamicSqlTrustMode)¶
Default: LEGACY. Values: LEGACY, SHADOW.
Dynamic SQL is frequently only partly known — the table is a literal but the
WHERE clause is a runtime parameter. SHADOW publishes exactly the same graph as
LEGACY but additionally reports how complete the materialization was, so you can
measure the affected surface. Neither mode filters output.
setReportDynamicSqlSitesAsErrors(boolean)¶
Default: false. Mirrors every non-resolved dynamic-SQL site into the error list,
where ordinary error-reading code will see it.
1 2 3 4 5 6 | |
Full lineage into report_daily, with the unknown predicate represented by an
fdr edge from the @where variable — but nothing tells you the site was
incomplete.
1 | |
The structured form of the same information is always available from
analyzer.getDynamicSqlSites(), whatever these options are set to.
setAssumeExternalScriptPassthrough(boolean)¶
Default: true. SQL Server's sp_execute_external_script runs a Python or R
script whose body GSP cannot read. By default GSP assumes the input dataset maps
positionally to the declared WITH RESULT SETS columns, and marks every such edge
effectType="external_script_passthrough" so it stays distinguishable from proven
lineage.
1 2 3 4 5 6 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
Lineage reaches scored_orders.
The passthrough edges and the RS-2 result set are gone. orders → RS-1 is still
reported, but lineage stops at the script boundary — scored_orders has no
upstream.
Choose true when a plausible-but-assumed edge is better than a gap, and read
effectType to tell the two apart; choose false when your consumer must only ever
show proven lineage.
10. Large inputs¶
setAutoDetectLargeFile(boolean)¶
Default: false. A very large script or manifest can exhaust the heap in a
single-threaded run. With this on, GSP measures the input against the thresholds
below and, if any is exceeded, delegates to ParallelDataFlowAnalyzer, which splits
the work across a bounded thread pool and merges the results. If delegation fails for
any reason, it falls back to single-threaded analysis with a warning.
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Thresholds¶
| Option | Default | Triggers delegation when… |
|---|---|---|
setLargeSqlInfoCountThreshold(int) |
1000 |
the input holds this many SQL entries |
setLargeSqlTotalSizeThreshold(long) |
26214400 (25 MB) |
total SQL text reaches this many bytes |
setLargeQueryCountThreshold(int) |
1000 |
a sqlflow/grabit manifest holds this many queries |
setLargeShardCountThreshold(int) |
10 |
a sharded manifest references this many shard files |
setLargeFileSplitSizeMB(int) |
5 |
files above this size are split into chunks |
setLargeSqlThresholdMultiplier(double) |
1.5 |
multiplier on the split size that defines a "large" single statement |
setEstimatedMemoryPerTaskMB(long) |
2560 (2.5 GB) |
caps the pool size so pool × this fits available memory |
setParallel(int)¶
Default: availableProcessors() / 2 − 1. Worker count for parallel analysis; 0
means auto-size from the CPU count.
Note
setCollectAuthoritativeLineageEvidence is forced off during parallel analysis,
because merged ids are remapped and cannot yet be correlated back to worker evidence.
11. Integration hooks¶
setHandleListener(DataFlowHandleListener)¶
Default: none. Receives progress callbacks throughout the run, and — through
isCanceled() — lets you stop a long analysis. Implement the interface and hand it to
the option:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
1 | |
setCollectAuthoritativeLineageEvidence(boolean)¶
Default: false. Collects an immutable semantic sidecar of same-run AST and
catalog facts, keyed by the ids in the returned dataflow, for consumers that project
lineage into the SLPC contract. It is opt-in so that ordinary runs pay nothing for the
bookkeeping.
1 2 3 4 | |
The sidecar never appears in the XML or JSON output.
12. Beyond Option¶
12.1 Consume the model in Java instead of the XML¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
1 2 | |
12.2 Other entry points on DataFlowAnalyzer¶
| Call | What it gives you |
|---|---|
setSqlEnv(TSQLEnv) |
Real catalog metadata (tables, columns, types). The single biggest accuracy improvement available — it resolves SELECT *, unqualified columns and cross-schema names exactly. CLI /env metadata.json. |
getDataFlow() |
The in-memory model, always populated after generateDataFlow(). |
getErrorMessages() |
Parse and analysis errors, including the orphan-column and dynamic-SQL diagnostics shown above. |
getDynamicSqlSites() |
Every dynamic-SQL execution site and whether it was statically resolved. |
traceView() |
View → base-table mapping as CSV, instead of column lineage. |
getVersion() / getReleaseDate() |
The engine version, for provenance stamping. |
traceView() on two chained views:
1 2 3 4 5 | |
1 2 | |
Both views trace back to the physical table, not to each other.
12.3 Command-line flags and the options they set¶
The DataFlowAnalyzer main method accepts a small set of flags:
| Flag | Sets |
|---|---|
/f <file> |
the SQL file to analyze |
/d <dir> |
a directory of SQL files |
/t <vendor> |
setVendor — default oracle |
/s |
setSimpleOutput(true) |
/text |
setTextFormat(true) (read only after /s) |
/i |
setIgnoreRecordSet(true) |
/j |
setShowJoin(true) |
/json |
print the SQLFlow JSON model instead of XML |
/traceView |
run traceView() (implies /s) |
/o <file> |
redirect output to a file |
/log |
write errors to dataflow.log |
/version |
print engine version and release date |
1 2 3 | |
The distributed CLI has many more flags
The SQLFlow command-line distribution wraps this class and exposes far more options
(/env, /showER, /transform, /lof, /filterRelationTypes, CSV output, …).
Those are documented in Configuration options.
13. Recipes¶
| Goal | Options |
|---|---|
| Populate a data catalog with table→table and column→column edges | setSimpleOutput(true) |
| Human-readable smoke test | setSimpleOutput(true), setTextFormat(true) |
| Explain why an edge exists, in a UI | default (full) output, setTransform(true), setTransformCoordinate(true) |
| Impact analysis ("what breaks if I drop this column?") | full output, read both fdd and fdr edges |
| Value-flow only, no row influence | filterRelationTypes("fdd") |
| Track business logic in UDFs | setSimpleOutput(true), setSimpleShowFunction(true), setSimpleShowUdfFunctionOnly(true) |
| Hide staging temp tables | setSimpleOutput(true), setIgnoreTemporaryTable(true) |
| Lineage from a read-only reporting query | setSimpleOutput(true), setSimpleShowTopSelectResultSet(true) |
| Merge many runs into one graph | setStartId(n) per run, setNormalizeOutput(true), setDefaultDatabase/setDefaultSchema |
| Audit how much lineage came from dynamic SQL | setDynamicSqlTrustMode(SHADOW), setReportDynamicSqlSitesAsErrors(true) |
| Analyze a multi-gigabyte export | setAutoDetectLargeFile(true), setParallel(0) |
Refreshing this page¶
This page is hand-written but machine-verified, so it is refreshed incrementally — you do not rewrite it, you diff the option surface and touch only what moved.
1. Find what changed. From the repository root, list the mutators on Option
in the release you are documenting and diff against the previous stamp:
1 2 3 4 | |
At the 4.2.8 stamp this prints 70 names. A different count means an option was added or removed; a same count can still hide a renamed one, so diff the list, not the number.
2. Cover each new option in the section matching what it does, and add its row
to the cheat sheet. Keep the entry shape: default, what it
is for, minimal SQL, real before/after output in === "..." tabs.
3. Re-run the samples you touched and paste the real output. Nothing on this
page may be written from memory — that is the site-wide sample-code rule
(site-docs/CLAUDE.md in the repository), and it is the only reason the
before/after blocks are trustworthy.
4. Re-check the known limitations. The /// warning and /// note blocks cite
open MantisBT issues (currently #4719 and #4720). When one is fixed, replace the
caveat with the working behavior rather than leaving a stale warning.
5. Update the stamp at the top: version, its TBaseType.releaseDate, today's
date, and the new option count.
6. Verify before publishing:
1 2 3 | |
This version stamp is NOT a release-bump site
The repository's CLAUDE.md lists six sites that must move on every version bump.
This page is not one of them, and must not be added. The stamp means "this is
the build the samples were produced on", not "this is the current release".
Advancing it without re-running the samples turns a true statement into a false
one — the page would claim verification that never happened.
See also¶
- Configuration options — the same engine organised by CLI flag and SQLFlow delivery mode.
- Join analysis — the semantic IR behind
setShowJoin. - API documentation — the generated Javadoc.
- Validation reports — measured lineage accuracy, including known limitations.