A literal is a value written directly in the SQL text, such as 'EXEMPLO' or 4242123499. That is where personal data usually is: taxpayer ID, name, email, phone number. The mask replaces the literals with *** in the SQL you see and download. It is on by default and applies to everything your account shows.
The number rule on this page applies from console 1.6.0 on. Before it, the number option hid only numbers with 6 digits or more, such as 4242123499, and left rownum <= 10 as it was. A report downloaded before the change follows the old rule: download it again to get the new rule.
What the mask hides
There are two options, and each works on its own:
- Quoted text. All text in single quotes becomes
'***', also in theN'...'andq'[...]'forms. Text cut off in the middle of the literal becomes'***. - Numbers. Every number used as a value becomes
***, short or long: in a comparison,IN,BETWEEN, assignment, function argument,SELECTlist,GROUP BYandFETCH FIRST. Only the position number inORDER BYstays as it is. The minus sign stays, and the number goes.
Both options also apply inside SQL comments (-- and /* */), where the application sometimes writes values, such as the screen name or the record id.
| In the trace | In the report |
|---|---|
select * from t where cpf='98765432100' and id=4242123499 | select * from t where cpf='***' and id=*** |
where obs=q'[it's]' and y=nq'{a}' and z=Q'!b!' | where obs=q'[***]' and y=nq'{***}' and z=Q'!***!' |
select * from t where nome='EXEMPLO DA SIL (truncated text) | select * from t where nome='*** |
where ORDEM = 40 and id in (1, 2, 3) and v between 5 and 10 | where ORDEM = *** and id in (***, ***, ***) and v between *** and *** |
update t set qtd = 7, preco = 1.5e3 where k = .5 and z = -3 | update t set qtd = ***, preco = *** where k = *** and z = -*** |
select a, count(*) from t group by 1 having count(*) > 1 order by 2 desc, 1 nulls last | select a, count(*) from t group by *** having count(*) > *** order by 2 desc, 1 nulls last |
select a from t order by decode(a, 1, 2), 3 fetch first 10 rows only | select a from t order by decode(a, ***, ***), 3 fetch first *** rows only |
select /* tela='CADASTRO', id=42 */ * from t | select /* tela='***', id=*** */ * from t |
What the mask does not hide
- Optimizer hints (
/*+ */), in full. Inselect /*+ parallel(t 4) */ * from t where rownum <= 10, the hint stays and only the10becomes***. - Table, column and object names, including those in double quotes (
"COL9") and those with digits (t1234567). - Binds, such as
:1,:b123456and:"SYS_B_0": the bind name stays, and the value never enters the report. - The CLIENT ID, the module, the action, the host and the file path, in the summary, and, in deadlocks, the database user, the machine and the program of each session.
- The name of the uploaded file and the names in the PL/SQL stack.
The mask changes what is displayed, not what WaitScope stores: the report on the server keeps the SQL as it is in the trace. To send less personal data, generate the trace without bind values and upload only the files of the operation you want to analyze.
Where the mask applies
In everything you see: the report page, the statement detail, the object page, the downloaded HTML, PDF and JSON, the Android app and the API. In the report, it covers every place where SQL text appears:
- SQL statements by contribution and Top statements by component and by class;
- the statement text, the Variants that cost the most table and Recursive SQL executed by this statement, in the statement detail;
- Longest depth-0 calls;
- Shareable texts;
- Errors, in the list of where each error appeared;
- Deadlocks, in the SQL of each session.
With either option on, the SQL ID of the variants also disappears: the Variants that cost the most table has no SQL ID column, and the SQL IDs column of Shareable texts shows hidden by the mask. The sql_id is computed from the text with the values and would make it possible to work out the hidden literal.
In SQL the database rejected, recorded in PARSE ERROR, the text appears only up to the first quote, followed by ***: in rejected SQL, there is no safe way to tell where each value ends (ORA errors in the trace).
Since the mask only changes the display, turning it off shows the original text again, also in old analyses.
Statements that differ only in their literals become one shape, with :s in place of quoted text and :n in place of numbers. The shape text no longer has literals, and the mask does not change it: it hides the literals of the variants. See SQL with literals instead of bind variables.
Bind values
Bind values are in the BINDS block of the trace, written at levels 4 and 12 of event 10046 or with binds => TRUE in DBMS_MONITOR. WaitScope ignores this block when reading the trace: the values do not enter the report, with or without the mask. They exist only in the uploaded file, which leaves the server when the analysis finishes.
Even so, prefer a trace without binds: level 8 of 10046 or DBMS_MONITOR with waits and without binds. See event 10046 levels.
Turn the mask on or off
- In the console, click your username, at the top of the screen, to open My account.
- In Report privacy, check or uncheck Hide quoted text in the SQL (cpf = '***').
- Check or uncheck Hide the numbers used as values in the SQL (id = ***).
- Click Save.
Result: the console shows “Report privacy saved.”, and the SQL of all your analyses comes out with the new choice, in the console, in the app and in future downloads.
The Android app follows the choice made in the console. Through the API, both options are in GET and PUT /api/v1/conta/privacidade, in the ocultar_textos and ocultar_numeros fields (account routes in API v1). A report you have already downloaded does not change: download it again to get the file with the new choice.
Where to go next
- Data retention, deletion and privacy: what the report stores and who sees it.
- SQL with literals instead of bind variables: when literals in the SQL cost parse time.
- Shareable texts: SQL without binds: the statements that differ only in their literals.