Skip to main content

Module fact_emit

Module fact_emit 

Source
Expand description

Emit declaration / reference / call facts plus privilege / dynamic-SQL / unknown facts.

Bridges the semantic-layer extractors (calls, dml-edges, privilege model, dynamic-SQL evidence, opacity reasons) and the declaration table into the normalized [Fact] stream defined by. Each emitter takes the typed per-family input + a FactProvenance and pushes minted facts into a FactStore.

“With evidence” (FACT-004): the privilege / dynamic-SQL / opacity payloads are deliberately lightweight — the evidence a consumer needs to defend the fact (the grant tuple, the dynamic-SQL site text, the opacity reason) travels in the payload string, and richer structured evidence is re-fetched from the originating crate’s model by FactId.

Keeping emission in one module means the engine wiring layer has a single call site per fact family and the FactId derivation stays consistent.

§/oracle evidence

  • DATABASE-REFERENCE.md PL/SQL Language Reference — the declaration / reference / call grammar 1:1 with the fact families.
  • LOW-LEVEL-CATALOGS.md Data Dictionary View Families — ALL_OBJECTS (declarations), ALL_DEPENDENCIES (call edges), ALL_IDENTIFIERS (references) are the server-side mirrors.

Structs§

CursorForLoopSite
One detected cursor FOR loop.
DetailFactSite
A site carrying a unit id plus a short detail string (the matched deprecated feature / non-deterministic construct).
ExceptionHandlerSite
One detected EXCEPTION WHEN <scope> THEN <body> handler.
HardcodedCredentialSite
One string literal that is, by strong syntactic context, a hardcoded secret (SEC003).
InvokerRightsSite
One unit declaring invoker’s rights (AUTHID CURRENT_USER) (SEC004).
IsNullIndexedSite
One <col> IS NULL predicate on a column the same source indexes (PERF003).
MissingInstrumentationSite
One routine body with no recognized instrumentation call. Reports absence only — STYLE001 (opt-in) decides whether that is a finding.
SynonymFactSite
One sensitive CREATE PUBLIC SYNONYM site (SEC005).
UnitFactSite
One unit whose RETURN type is a REF CURSOR (SEC007), one function with row-level DML in its body (QUAL007), or one unbounded BULK COLLECT (QUAL003). All carry only the unit id — the rule explains; the fact reports presence.

Functions§

emit_call_facts
Emit one DependencyEdge fact per call site. from_logical_id is the routine the call appeared in; the callee path is joined with . into the edge target.
emit_cross_schema_write_facts
Emit CrossSchemaWrite facts (DEP001).
emit_cursor_for_loop_facts
Emit one CursorForLoop fact per site, mirroring emit_exception_handler_facts.
emit_declaration_facts
Emit one Declaration fact per registered declaration. Returns the count emitted (post-dedup).
emit_declarations_from
Convenience: emit a declaration fact for every entry a DeclLike source yields. The trait keeps this module free of a hard plsql-symbols dependency (which would invert the layer order — symbols depends on ir, not the reverse).
emit_deprecated_feature_facts
Emit DeprecatedFeature facts (QUAL005).
emit_deterministic_misuse_facts
Emit DeterministicMisuse facts (QUAL008).
emit_dml_in_function_facts
Emit DmlInFunction facts (QUAL007).
emit_dynamic_sql_facts
Emit one DynamicSqlEvidence fact per recognised dynamic-SQL site. site carries the evidence — typically the logical id of the unit plus a fragment/classification summary from DynamicSqlEvidence.
emit_exception_handler_facts
Emit one ExceptionHandler fact per detected handler so QUAL001 / QUAL004 can consume them via by_kind like every other fact-based rule.
emit_flow_env_facts
Emit flow-lattice facts for every tracked name in a FlowEnv.
emit_flow_facts
Emit flow-lattice facts from explicit (name, ValueFlow) rows.
emit_hardcoded_credential_facts
Emit one HardcodedCredential fact per site (SEC003).
emit_invoker_rights_facts
Emit one InvokerRights fact per site (SEC004).
emit_is_null_on_indexed_column_facts
Emit IsNullOnIndexedColumn facts (PERF003).
emit_log_without_reraise_facts
Emit LogWithoutReraise facts (QUAL002).
emit_missing_instrumentation_facts
Emit one MissingInstrumentation fact per site.
emit_mutating_table_trigger_facts
Emit MutatingTableTrigger facts (QUAL006).
emit_privilege_facts
Emit one Privilege fact per resolved (grantee, privilege, on) triple. The triple is the evidence: who can do what to which object. Returns the post-dedup count.
emit_ref_cursor_return_facts
Emit RefCursorReturn facts (SEC007).
emit_reference_facts
Emit one Reference fact per (from_decl, to_logical_id) pair.
emit_sensitive_public_synonym_facts
Emit SensitivePublicSynonym facts (SEC005).
emit_unbounded_bulk_collect_facts
Emit UnboundedBulkCollect facts (QUAL003).
emit_unknown_facts
Emit one Opacity fact per (target_logical_id, reason) pair — the “unknown” family. reason is the evidence string (typically a stringified UnknownReason) so a consumer can explain why the analyser could not see through the target.
scan_cross_schema_write
DEP001: a DML statement whose target is schema-qualified to a schema other than the unit’s own (cross-schema write surface). Unit schema = first dotted segment of unit_logical_id.
scan_cursor_for_loops
Scan a routine source for cursor FOR loops, yielding one CursorForLoopSite per loop. Text-level, mirroring scan_exception_handlers. A numeric range loop (FOR i IN 1..10 LOOP) is not a cursor loop and yields no site (R13: a false fact is worse than a missing one).
scan_deprecated_features
QUAL005: well-known deprecated / legacy constructs. Conservative (R13): only unambiguous, widely policy-flagged forms; literals are masked so a mention in a string never matches. One site per distinct feature found.
scan_deterministic_misuse
QUAL008: a DETERMINISTIC function whose body contains a non-deterministic construct. One site per distinct construct.
scan_dml_in_function
QUAL007: a FUNCTION whose body performs row-level DML. Only fires when the source is a function (the function keyword is present as a word) and body_has_dml (R13: a procedure with DML is normal and is not flagged here).
scan_exception_handlers
Scan a routine source for its exception section and yield one ExceptionHandlerSite per WHEN ... THEN ... handler.
scan_hardcoded_credentials
Scan source for hardcoded credentials: a credential marker (in code position, never inside a literal) immediately followed (same statement, before ;) by a quoted string literal. Text-level + conservative, mirroring scan_exception_handlers.
scan_invoker_rights
Scan source for an AUTHID CURRENT_USER clause. Literal contents are masked first so the phrase can’t self-match inside a string; whitespace between authid and current_user is collapsed. Conservative: AUTHID DEFINER (or absence) yields no site. At most one site per unit.
scan_is_null_on_indexed_column
PERF003: a <col> IS NULL predicate where the same source declares an index whose key list contains col. B-tree indexes do not store all-NULL keys, so the predicate forces a full scan. R13: requires BOTH the index DDL and the predicate in this source; catalog-only indexes are out of this source-level scope. is null is not a substring of is not null, so negated predicates never match.
scan_log_without_reraise
QUAL002: an exception handler that instruments/logs but neither re-raises nor signals — the error is recorded then swallowed. At most one site per unit. Mirrors the lightweight exception- section split used by scan_exception_handlers.
scan_missing_instrumentation
Scan a routine source: if it has a body (BEGIN) but no recognized instrumentation marker, yield a single MissingInstrumentationSite. A spec with no body yields nothing (R13 — we only report a unit we can see executes).
scan_mutating_table_trigger
QUAL006: a FOR EACH ROW trigger whose body references its own base table in a query/DML (ORA-04091 mutating-table hazard). R13-conservative: requires a clean on <table> extraction and for each row; otherwise no fact.
scan_ref_cursor_return
SEC007: a function returning a REF CURSOR. Detects the common RETURN SYS_REFCURSOR and explicit RETURN REF CURSOR forms (strongly-typed named ref-cursor returns need type resolution and are out of this text-level scope — R13, documented).
scan_sensitive_public_synonym
SEC005: a CREATE [OR REPLACE] PUBLIC SYNONYM <syn> FOR <tgt> where the synonym or its target name matches the sensitivity heuristic. Literal-masked, conservative: a non-public synonym or a benign name yields no fact.
scan_unbounded_bulk_collect
QUAL003: a BULK COLLECT INTO with no LIMIT in the same statement — unbounded PGA materialization. One site per offending statement.