Skip to content

Commit feb1290

Browse files
Jamesclaude
authored andcommitted
Add readme.md to the 18 demo folders that had none
Every demo folder now carries one, 49 of 49. Each was written from the demo's actual source and, where the demo runs, from its real output: the commands and the sample output in these files were executed, not composed. 21 documented -Dexec.mainClass values were checked against the source tree, and 13 demos were run end to end to confirm the output shown matches. Two of the new files report that the demo does not work, rather than inventing a usage example: events ProcessSQLStatement reads a hardcoded C:\Users\DELL\Downloads\20240311110800487_mssql_sql\data.sql left behind by whoever wrote it. processTokenList stops with "syntax error ... near: $" -- its whole purpose is merging ${var} placeholders into one identifier token so templated SQL parses, and that is not taking effect against this parser build. The setTokenListHandle wiring is still worth reading; the result is not. snowflake Evaluates JavaScript with Nashorn, removed from the JDK in 15, so it needs Java 8-14. Its snowflake.js is the repository's only classpath resource and had been sitting in src/main/java where nothing copies it, which is why the demo had never run; that was fixed separately. Two folders are not demos and say so: removeSpecialConditions has no main() and is exercised through its test, and utils holds shared helpers behind the sqlenv demo. Where a demo has a near neighbour the reader probably wants instead, the file says which: removeCondition vs removeSpecialConditions vs sqlrefactor, scriptwriter as the round-trip that modifysql depends on, sqlenv vs gettablecolumns' JDBC-backed runGetTableColumn, findproceduralsql as triage ahead of analyzesp and callgraph. mvn clean test: 144 tests, the same 3 known analyzespTest failures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012qPRpoD8exYRrUmbfXXWXj
1 parent 55e5b87 commit feb1290

18 files changed

Lines changed: 538 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## Description
2+
3+
Builds a call graph for a PL/SQL package: every routine it declares, how those
4+
routines call each other, and where each one sits in the source. Emitted as
5+
JSON so it can feed a visualiser or an impact-analysis step.
6+
7+
## Usage
8+
9+
```
10+
java CallGraphDemo /f <path_to_sql_file> [/o <output file path>]
11+
```
12+
13+
```bash
14+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.callgraph.CallGraphDemo \
15+
-Dexec.args="/f samples/callgraph/sample_package.sql" -Dexec.classpathScope=compile
16+
```
17+
18+
```json
19+
{
20+
"boundProgram": {
21+
"routines": [
22+
{"routineId": "emp_pkg.log_action/NP(1)", "kind": "NESTED_PROCEDURE", "name": "log_action",
23+
"package": "emp_pkg", "paramCount": 1,
24+
"sourceAnchor": {"startLine": 3, "startCol": 5, "endLine": 6, "endCol": 19}},
25+
...
26+
],
27+
"objectRefs": 5,
28+
```
29+
30+
`routineId` encodes package, name, kind (`NP` nested procedure, `NF` nested
31+
function) and arity, so overloads stay distinct. `sourceAnchor` is the routine's
32+
span in the input file.
33+
34+
`samples/callgraph/sample_package.sql` is a small Oracle package kept for this
35+
demo.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Description
2+
3+
Walks the expressions in a SQL script and evaluates what it can. Columns have
4+
no value outside a database, so they are substituted with 0 and reported; from
5+
there any expression built only from constants is folded to a result.
6+
7+
## Usage
8+
9+
```
10+
java EvaluatorDemo [/f <path_to_sql_file>] [/t <database type>]
11+
```
12+
13+
```bash
14+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.evaluator.EvaluatorDemo \
15+
-Dexec.args="/f q.sql /t oracle" -Dexec.classpathScope=compile
16+
```
17+
18+
```text
19+
Output:
20+
a.id is a column, set value to 0,...
21+
b.name is a column, set value to 0,...
22+
0
23+
0
24+
100
25+
26+
DbVendor:dbvoracle, Time Escaped: 1306ms
27+
```
28+
29+
The trailing `100` is the literal in the select list, folded as a constant.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## Description
2+
3+
Two callbacks the parser offers, letting you intervene *during* a parse rather
4+
than walking the tree afterwards.
5+
6+
| Class | Callback | Purpose |
7+
|-------|----------|---------|
8+
| `ProcessSQLStatement` | `ISQLStatementHandle` | Fires per statement as a script is parsed, so a large script can be processed incrementally instead of held whole |
9+
| `processTokenList` | `ITokenListHandle` | Fires on the token list before parsing, so text that is not legal SQL can be rewritten into something that is |
10+
11+
`processTokenList` exists for templated SQL. A script full of
12+
`${tx_date_yyyymm}` placeholders will not parse, so the handler merges `$`, `{`,
13+
name, `}` into a single identifier token first.
14+
15+
## Usage
16+
17+
Neither takes arguments; both are configured inline.
18+
19+
```bash
20+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.events.processTokenList \
21+
-Dexec.classpathScope=compile
22+
```
23+
24+
> **Both demos fail as shipped.**
25+
>
26+
> `ProcessSQLStatement` reads a hardcoded path,
27+
> `C:\Users\DELL\Downloads\20240311110800487_mssql_sql\data.sql`, left over from
28+
> whoever wrote it. Point `sqlfile` at something real before running it.
29+
>
30+
> `processTokenList` currently stops with `syntax error … near: $`, so its token
31+
> merging is not taking effect against this parser build. The callback wiring is
32+
> still worth reading as an example of `setTokenListHandle`; the result is not.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
## Description
2+
3+
Lists every string literal and numeric constant in a SQL script. The kind of
4+
sweep you would run before parameterising hard-coded values, or to find
5+
embedded secrets and magic numbers.
6+
7+
## Usage
8+
9+
```
10+
java findConstants <scriptfile> [/t <database type>]
11+
```
12+
13+
`/t` defaults to `oracle`.
14+
15+
```bash
16+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.findConstants.findConstants \
17+
-Dexec.args="q.sql /t oracle" -Dexec.classpathScope=compile
18+
```
19+
20+
For `SELECT a.id, b.name, 100 AS n FROM ta a JOIN tb b ON a.id = b.id WHERE a.x > 1 AND 'k' = 'k';`
21+
22+
```text
23+
string literals and numeric constants:
24+
100, 1, 'k', 'k'
25+
```
26+
27+
Constants are reported once per occurrence, not deduplicated: `'k'` appears
28+
twice above because the query contains it twice.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
## Description
2+
3+
Scans a directory of `.sql` files and picks out the ones containing procedural
4+
SQL — stored procedures, functions, triggers, packages — copying them to a
5+
second directory.
6+
7+
Useful for triaging a large dump before analysis, since procedural code is what
8+
tends to need the heavier tooling (`analyzesp`, `callgraph`, `tracedatalineage`).
9+
10+
## Usage
11+
12+
```
13+
java FindProceduralSqlFiles <dbvendor> <source-sql-dir> <output-sql-dir>
14+
```
15+
16+
`dbvendor` is `oracle`, `mssql` or `sqlserver`. Running it with no arguments
17+
prints exactly that.
18+
19+
```bash
20+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.findproceduralsql.FindProceduralSqlFiles \
21+
-Dexec.args="oracle /path/to/scripts /path/to/procedural-only" \
22+
-Dexec.classpathScope=compile
23+
```
24+
25+
Both directories are filesystem paths; the output directory receives copies, so
26+
the source is left untouched.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Description
2+
3+
Prints which parser build you are actually running: version, release date,
4+
whether it is the full or trial edition, and every SQL dialect it supports.
5+
6+
Useful as a first check when a demo behaves unexpectedly, since most surprises
7+
come down to the parser version or the trial-vs-full distinction.
8+
9+
## Usage
10+
11+
Takes no arguments.
12+
13+
```bash
14+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.listGSPInfo.listGSPInfo \
15+
-Dexec.classpathScope=compile
16+
```
17+
18+
```text
19+
Version: 4.1.5.15,Release date: 2026-07-12, Full version:false
20+
Supported DBs: 40/45,[dbvathena, dbvazuresql, dbvbigquery, ... dbvvertica]
21+
```
22+
23+
`Full version:false` means the trial build. `40/45` is dialects implemented out
24+
of dialects defined in `EDbVendor`.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Description
2+
3+
Adds conditions to an existing `SELECT`'s `WHERE` clause through the parse
4+
tree rather than by string concatenation: a join predicate between two tables,
5+
plus bind-parameter placeholders.
6+
7+
Doing this on the AST is what keeps it correct when the original `WHERE` is
8+
already non-trivial, where appending ` AND ...` to the text would not be.
9+
10+
## Usage
11+
12+
Takes no arguments; the query is inline in `ModifySelect.java`.
13+
14+
```bash
15+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.modifySelect.ModifySelect \
16+
-Dexec.classpathScope=compile
17+
```
18+
19+
```text
20+
Original SQL:
21+
SELECT A.COLUMN1, B.COLUMN2 from TABLE1 A, TABLE2 B where A.COLUMN1=B.COLUMN1
22+
Modified SQL:
23+
SELECT A.COLUMN1, B.COLUMN2 from TABLE1 A, TABLE2 B where A.COLUMN1=B.COLUMN1 AND A.newcolumn=B.newcolumn AND A.newcolumn=? AND B.newcolumn=?
24+
```
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## Description
2+
3+
Three small demos of rewriting SQL through the parse tree instead of by string
4+
manipulation. Each takes no arguments; the query is inline in its source.
5+
6+
| Class | What it rewrites |
7+
|-------|------------------|
8+
| `replaceTablename` | Swaps a table reference for a derived table, rewriting every qualified column that pointed at it |
9+
| `replaceConstant` | Turns literals into `?` bind parameters |
10+
| `add2SQL` | Adds conditions to a `WHERE` clause |
11+
12+
## Usage
13+
14+
```bash
15+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.modifysql.replaceTablename \
16+
-Dexec.classpathScope=compile
17+
```
18+
19+
```text
20+
input sql:
21+
select table1.col1, table2.col2
22+
from table1, table2
23+
where table1.foo > table2.foo
24+
25+
output sql:
26+
select table1.col1, table3.col2
27+
from table1, (tableX join tableY using (id)) as table3
28+
where table1.foo > table3.foo
29+
```
30+
31+
Note that `table2.col2` and `table2.foo` both became `table3.…`: the aliases
32+
follow the substitution, which is the part that string replacement gets wrong.
33+
34+
`replaceConstant` turns `VALUES ('arun','deep')` into `VALUES (?,?)` — the usual
35+
first step in retrofitting prepared statements onto generated SQL.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## Description
2+
3+
Two demos about the cost of creating parsers rather than the cost of parsing.
4+
5+
Building a `TGSqlParser` loads the grammar tables for its dialect, which is by
6+
far the most expensive part of a single parse — roughly a second in the run
7+
below. Pooling parsers amortises that away, which matters for a service parsing
8+
many statements.
9+
10+
| Class | What it does |
11+
|-------|--------------|
12+
| `ParserPoolDemo` | Walks through the pool's behaviour: initialisation cost, then reuse |
13+
| `ParserPoolBenchmark` | Timed comparison of pooled versus non-pooled parsing |
14+
15+
## Usage
16+
17+
Neither takes arguments.
18+
19+
```bash
20+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.performance.ParserPoolDemo \
21+
-Dexec.classpathScope=compile
22+
```
23+
24+
```text
25+
========================================
26+
SQL Parser Pool Demonstration
27+
========================================
28+
29+
=== Initialization Phase ===
30+
Loading grammar tables (one-time cost)...
31+
Grammar tables loaded in 907 ms
32+
```
33+
34+
`ParserPoolBenchmark` runs longer; the API it exercises is
35+
`TParserPoolFactory`.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## Description
2+
3+
Removes conditions from a `WHERE` clause through the parse tree, leaving the
4+
rest of the statement, including its `GROUP BY`, intact.
5+
6+
Useful for stripping tenant or environment filters out of a query before
7+
analysing it, or for producing the "unfiltered" form of a report query.
8+
9+
Compare `removeSpecialConditions`, which targets particular condition shapes,
10+
and `sqlrefactor`, which cleans up redundant parentheses.
11+
12+
## Usage
13+
14+
Takes no arguments; the query is inline in `removeCondition.java`.
15+
16+
```bash
17+
mvn -q exec:java -Dexec.mainClass=gudusoft.gsqlparser.demos.removeCondition.removeCondition \
18+
-Dexec.classpathScope=compile
19+
```
20+
21+
```text
22+
SELECT SUM (d.amt)
23+
FROM summit.cntrb_detail d
24+
WHERE d.fund_coll_attrb IN ( 'ShanXi University' )
25+
AND d.fund_acct IN ( 'Eclipse.org' )
26+
GROUP BY d.id;
27+
```
28+
29+
There is also a test covering this demo at
30+
`src/test/java/gudusoft/gsqlparser/removeConditionTest/`.

0 commit comments

Comments
 (0)