rawsql-ts 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +161 -875
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +22 -20
- package/dist/esm/index.min.js.map +4 -4
- package/dist/esm/models/Clause.d.ts +15 -3
- package/dist/esm/models/Clause.js +2 -1
- package/dist/esm/models/Clause.js.map +1 -1
- package/dist/esm/models/CreateTableQuery.d.ts +3 -0
- package/dist/esm/models/CreateTableQuery.js +5 -4
- package/dist/esm/models/CreateTableQuery.js.map +1 -1
- package/dist/esm/models/DDLStatements.d.ts +71 -0
- package/dist/esm/models/DDLStatements.js +63 -0
- package/dist/esm/models/DDLStatements.js.map +1 -1
- package/dist/esm/models/KeywordTrie.d.ts +2 -3
- package/dist/esm/models/KeywordTrie.js +26 -27
- package/dist/esm/models/KeywordTrie.js.map +1 -1
- package/dist/esm/models/SqlPrintToken.d.ts +1 -0
- package/dist/esm/models/SqlPrintToken.js +1 -0
- package/dist/esm/models/SqlPrintToken.js.map +1 -1
- package/dist/esm/parsers/CheckpointStatementParser.d.ts +8 -0
- package/dist/esm/parsers/CheckpointStatementParser.js +14 -0
- package/dist/esm/parsers/CheckpointStatementParser.js.map +1 -0
- package/dist/esm/parsers/ClusterStatementParser.d.ts +8 -0
- package/dist/esm/parsers/ClusterStatementParser.js +14 -0
- package/dist/esm/parsers/ClusterStatementParser.js.map +1 -0
- package/dist/esm/parsers/CommandExpressionParser.js.map +1 -1
- package/dist/esm/parsers/CommentOnParser.d.ts +23 -0
- package/dist/esm/parsers/CommentOnParser.js +61 -0
- package/dist/esm/parsers/CommentOnParser.js.map +1 -0
- package/dist/esm/parsers/CommonTableParser.d.ts +5 -1
- package/dist/esm/parsers/CommonTableParser.js +94 -16
- package/dist/esm/parsers/CommonTableParser.js.map +1 -1
- package/dist/esm/parsers/CreateIndexParser.js +12 -6
- package/dist/esm/parsers/CreateIndexParser.js.map +1 -1
- package/dist/esm/parsers/CreateTableParser.d.ts +2 -0
- package/dist/esm/parsers/CreateTableParser.js +11 -2
- package/dist/esm/parsers/CreateTableParser.js.map +1 -1
- package/dist/esm/parsers/ExplainStatementParser.js.map +1 -1
- package/dist/esm/parsers/FullNameParser.js +35 -3
- package/dist/esm/parsers/FullNameParser.js.map +1 -1
- package/dist/esm/parsers/OrderByClauseParser.js.map +1 -1
- package/dist/esm/parsers/ReindexStatementParser.d.ts +8 -0
- package/dist/esm/parsers/ReindexStatementParser.js +14 -0
- package/dist/esm/parsers/ReindexStatementParser.js.map +1 -0
- package/dist/esm/parsers/SelectQueryParser.js.map +1 -1
- package/dist/esm/parsers/SourceParser.js +6 -1
- package/dist/esm/parsers/SourceParser.js.map +1 -1
- package/dist/esm/parsers/SqlParser.d.ts +12 -2
- package/dist/esm/parsers/SqlParser.js +117 -251
- package/dist/esm/parsers/SqlParser.js.map +1 -1
- package/dist/esm/parsers/SqlPrintTokenParser.d.ts +1 -0
- package/dist/esm/parsers/SqlPrintTokenParser.js +32 -4
- package/dist/esm/parsers/SqlPrintTokenParser.js.map +1 -1
- package/dist/esm/parsers/SqlTokenizer.d.ts +5 -0
- package/dist/esm/parsers/SqlTokenizer.js +181 -67
- package/dist/esm/parsers/SqlTokenizer.js.map +1 -1
- package/dist/esm/parsers/UsingClauseParser.js.map +1 -1
- package/dist/esm/parsers/VacuumStatementParser.d.ts +8 -0
- package/dist/esm/parsers/VacuumStatementParser.js +14 -0
- package/dist/esm/parsers/VacuumStatementParser.js.map +1 -0
- package/dist/esm/tokenReaders/CommandTokenReader.js +22 -4
- package/dist/esm/tokenReaders/CommandTokenReader.js.map +1 -1
- package/dist/esm/tokenReaders/StringSpecifierTokenReader.d.ts +2 -0
- package/dist/esm/tokenReaders/StringSpecifierTokenReader.js +30 -13
- package/dist/esm/tokenReaders/StringSpecifierTokenReader.js.map +1 -1
- package/dist/esm/tokenReaders/TokenReaderManager.d.ts +0 -7
- package/dist/esm/tokenReaders/TokenReaderManager.js +16 -48
- package/dist/esm/tokenReaders/TokenReaderManager.js.map +1 -1
- package/dist/esm/transformers/AliasRenamer.d.ts +1 -0
- package/dist/esm/transformers/AliasRenamer.js +7 -1
- package/dist/esm/transformers/AliasRenamer.js.map +1 -1
- package/dist/esm/transformers/CTECollector.d.ts +5 -2
- package/dist/esm/transformers/CTECollector.js +49 -0
- package/dist/esm/transformers/CTECollector.js.map +1 -1
- package/dist/esm/transformers/CTEDependencyTracer.d.ts +6 -1
- package/dist/esm/transformers/CTEDependencyTracer.js +44 -2
- package/dist/esm/transformers/CTEDependencyTracer.js.map +1 -1
- package/dist/esm/transformers/CTEDisabler.d.ts +6 -0
- package/dist/esm/transformers/CTEDisabler.js +19 -0
- package/dist/esm/transformers/CTEDisabler.js.map +1 -1
- package/dist/esm/transformers/CTERenamer.js +5 -2
- package/dist/esm/transformers/CTERenamer.js.map +1 -1
- package/dist/esm/transformers/ColumnReferenceCollector.d.ts +4 -0
- package/dist/esm/transformers/ColumnReferenceCollector.js +69 -1
- package/dist/esm/transformers/ColumnReferenceCollector.js.map +1 -1
- package/dist/esm/transformers/DeleteResultSelectConverter.js.map +1 -1
- package/dist/esm/transformers/DynamicQueryBuilder.d.ts +87 -11
- package/dist/esm/transformers/DynamicQueryBuilder.js +237 -9
- package/dist/esm/transformers/DynamicQueryBuilder.js.map +1 -1
- package/dist/esm/transformers/ExistsPredicateInjector.d.ts +33 -0
- package/dist/esm/transformers/ExistsPredicateInjector.js +294 -0
- package/dist/esm/transformers/ExistsPredicateInjector.js.map +1 -0
- package/dist/esm/transformers/FixtureCteBuilder.js +5 -2
- package/dist/esm/transformers/FixtureCteBuilder.js.map +1 -1
- package/dist/esm/transformers/InsertResultSelectConverter.d.ts +1 -0
- package/dist/esm/transformers/InsertResultSelectConverter.js +28 -7
- package/dist/esm/transformers/InsertResultSelectConverter.js.map +1 -1
- package/dist/esm/transformers/LinePrinter.d.ts +4 -2
- package/dist/esm/transformers/LinePrinter.js +93 -22
- package/dist/esm/transformers/LinePrinter.js.map +1 -1
- package/dist/esm/transformers/MergeResultSelectConverter.js.map +1 -1
- package/dist/esm/transformers/OptimizeUnusedLeftJoins.d.ts +33 -0
- package/dist/esm/transformers/OptimizeUnusedLeftJoins.js +333 -0
- package/dist/esm/transformers/OptimizeUnusedLeftJoins.js.map +1 -0
- package/dist/esm/transformers/PruneOptionalConditionBranches.d.ts +10 -0
- package/dist/esm/transformers/PruneOptionalConditionBranches.js +197 -0
- package/dist/esm/transformers/PruneOptionalConditionBranches.js.map +1 -0
- package/dist/esm/transformers/SchemaCollector.d.ts +3 -0
- package/dist/esm/transformers/SchemaCollector.js +37 -1
- package/dist/esm/transformers/SchemaCollector.js.map +1 -1
- package/dist/esm/transformers/SelectValueCollector.d.ts +5 -0
- package/dist/esm/transformers/SelectValueCollector.js +44 -2
- package/dist/esm/transformers/SelectValueCollector.js.map +1 -1
- package/dist/esm/transformers/SqlParamInjector.d.ts +5 -1
- package/dist/esm/transformers/SqlParamInjector.js +47 -11
- package/dist/esm/transformers/SqlParamInjector.js.map +1 -1
- package/dist/esm/transformers/SqlPrinter.js +8 -2
- package/dist/esm/transformers/SqlPrinter.js.map +1 -1
- package/dist/esm/transformers/TableSourceCollector.d.ts +9 -1
- package/dist/esm/transformers/TableSourceCollector.js +72 -5
- package/dist/esm/transformers/TableSourceCollector.js.map +1 -1
- package/dist/esm/transformers/UpdateResultSelectConverter.js.map +1 -1
- package/dist/esm/transformers/UpstreamSelectQueryFinder.d.ts +5 -0
- package/dist/esm/transformers/UpstreamSelectQueryFinder.js +46 -1
- package/dist/esm/transformers/UpstreamSelectQueryFinder.js.map +1 -1
- package/dist/esm/utils/CommentUtils.d.ts +1 -0
- package/dist/esm/utils/CommentUtils.js +14 -4
- package/dist/esm/utils/CommentUtils.js.map +1 -1
- package/dist/esm/utils/MultiQuerySplitter.d.ts +7 -11
- package/dist/esm/utils/MultiQuerySplitter.js +105 -66
- package/dist/esm/utils/MultiQuerySplitter.js.map +1 -1
- package/dist/esm/utils/ParameterRemover.d.ts +4 -0
- package/dist/esm/utils/ParameterRemover.js +23 -0
- package/dist/esm/utils/ParameterRemover.js.map +1 -1
- package/dist/esm/utils/ScopeResolver.d.ts +5 -2
- package/dist/esm/utils/ScopeResolver.js +37 -18
- package/dist/esm/utils/ScopeResolver.js.map +1 -1
- package/dist/esm/utils/charLookupTable.d.ts +6 -0
- package/dist/esm/utils/charLookupTable.js +9 -1
- package/dist/esm/utils/charLookupTable.js.map +1 -1
- package/dist/esm/utils/serialTypeNormalization.d.ts +15 -0
- package/dist/esm/utils/serialTypeNormalization.js +55 -0
- package/dist/esm/utils/serialTypeNormalization.js.map +1 -0
- package/dist/esm/utils/stringUtils.js +51 -26
- package/dist/esm/utils/stringUtils.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +21 -19
- package/dist/index.min.js.map +4 -4
- package/dist/models/Clause.js +2 -1
- package/dist/models/Clause.js.map +1 -1
- package/dist/models/CreateTableQuery.js +5 -4
- package/dist/models/CreateTableQuery.js.map +1 -1
- package/dist/models/DDLStatements.js +14 -1
- package/dist/models/DDLStatements.js.map +1 -1
- package/dist/models/KeywordTrie.js +26 -27
- package/dist/models/KeywordTrie.js.map +1 -1
- package/dist/models/SqlPrintToken.js +1 -0
- package/dist/models/SqlPrintToken.js.map +1 -1
- package/dist/parsers/CommentOnParser.js +65 -0
- package/dist/parsers/CommentOnParser.js.map +1 -0
- package/dist/parsers/CreateIndexParser.js +12 -6
- package/dist/parsers/CreateIndexParser.js.map +1 -1
- package/dist/parsers/CreateTableParser.js +11 -2
- package/dist/parsers/CreateTableParser.js.map +1 -1
- package/dist/parsers/FullNameParser.js +35 -3
- package/dist/parsers/FullNameParser.js.map +1 -1
- package/dist/parsers/SourceParser.js +6 -1
- package/dist/parsers/SourceParser.js.map +1 -1
- package/dist/parsers/SqlParser.js +93 -307
- package/dist/parsers/SqlParser.js.map +1 -1
- package/dist/parsers/SqlPrintTokenParser.js +31 -3
- package/dist/parsers/SqlPrintTokenParser.js.map +1 -1
- package/dist/parsers/SqlTokenizer.js +176 -67
- package/dist/parsers/SqlTokenizer.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/models/Clause.d.ts +6 -1
- package/dist/src/models/CreateTableQuery.d.ts +3 -0
- package/dist/src/models/DDLStatements.d.ts +15 -0
- package/dist/src/models/KeywordTrie.d.ts +2 -3
- package/dist/src/models/SqlPrintToken.d.ts +1 -0
- package/dist/src/parsers/CommentOnParser.d.ts +23 -0
- package/dist/src/parsers/CreateTableParser.d.ts +2 -0
- package/dist/src/parsers/SqlParser.d.ts +8 -2
- package/dist/src/parsers/SqlPrintTokenParser.d.ts +1 -0
- package/dist/src/parsers/SqlTokenizer.d.ts +5 -0
- package/dist/src/tokenReaders/StringSpecifierTokenReader.d.ts +2 -0
- package/dist/src/tokenReaders/TokenReaderManager.d.ts +0 -7
- package/dist/src/transformers/DynamicQueryBuilder.d.ts +26 -0
- package/dist/src/transformers/InsertResultSelectConverter.d.ts +1 -0
- package/dist/src/transformers/LinePrinter.d.ts +4 -2
- package/dist/src/transformers/PruneOptionalConditionBranches.d.ts +10 -0
- package/dist/src/utils/CommentUtils.d.ts +1 -0
- package/dist/src/utils/MultiQuerySplitter.d.ts +7 -11
- package/dist/src/utils/serialTypeNormalization.d.ts +4 -0
- package/dist/tokenReaders/CommandTokenReader.js +22 -4
- package/dist/tokenReaders/CommandTokenReader.js.map +1 -1
- package/dist/tokenReaders/StringSpecifierTokenReader.js +30 -13
- package/dist/tokenReaders/StringSpecifierTokenReader.js.map +1 -1
- package/dist/tokenReaders/TokenReaderManager.js +16 -48
- package/dist/tokenReaders/TokenReaderManager.js.map +1 -1
- package/dist/transformers/DynamicQueryBuilder.js +114 -2
- package/dist/transformers/DynamicQueryBuilder.js.map +1 -1
- package/dist/transformers/InsertResultSelectConverter.js +22 -3
- package/dist/transformers/InsertResultSelectConverter.js.map +1 -1
- package/dist/transformers/LinePrinter.js +93 -22
- package/dist/transformers/LinePrinter.js.map +1 -1
- package/dist/transformers/PruneOptionalConditionBranches.js +201 -0
- package/dist/transformers/PruneOptionalConditionBranches.js.map +1 -0
- package/dist/tsconfig.browser.tsbuildinfo +1 -1
- package/dist/utils/CommentUtils.js +14 -4
- package/dist/utils/CommentUtils.js.map +1 -1
- package/dist/utils/MultiQuerySplitter.js +105 -66
- package/dist/utils/MultiQuerySplitter.js.map +1 -1
- package/dist/utils/serialTypeNormalization.js +19 -0
- package/dist/utils/serialTypeNormalization.js.map +1 -1
- package/dist/utils/stringUtils.js +42 -23
- package/dist/utils/stringUtils.js.map +1 -1
- package/package.json +65 -64
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -1,879 +1,165 @@
|
|
|
1
|
-
# rawsql-ts
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-

|
|
5
|
-

|
|
6
|
-

|
|
7
|
-

|
|
8
|
-
|
|
9
|
-
🌐 [Online Demo (GitHub Pages)](https://mk3008.github.io/rawsql-ts/)
|
|
10
|
-
|
|
11
|
-
rawsql-ts is a high-performance SQL parser and AST transformer library written in TypeScript. It empowers you to represent raw SQL as objects, enabling flexible manipulation of SQL statements directly within your program. This object-oriented approach allows for partial transformation, decomposition into manageable components, and recombination as needed, dramatically improving the maintainability and reusability of complex SQL.
|
|
12
|
-
|
|
13
|
-
It is designed for extensibility and advanced SQL analysis, with initial focus on PostgreSQL syntax but not limited to it. The library enables easy SQL parsing, transformation, and analysis for a wide range of SQL dialects.
|
|
14
|
-
|
|
15
|
-
> [!Note]
|
|
16
|
-
> This library is currently in beta. The API may change until the v1.0 release.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Key Features
|
|
21
|
-
|
|
22
|
-
- Zero dependencies: fully self-contained and lightweight
|
|
23
|
-
- High-speed SQL parsing and AST analysis (over 3x faster than major libraries)
|
|
24
|
-
- Rich utilities for SQL structure transformation and analysis
|
|
25
|
-
- Advanced SQL formatting capabilities, including multi-line formatting and customizable styles
|
|
26
|
-
- **Programmatic CTE Management** - Add, remove, and manipulate Common Table Expressions (CTEs) programmatically with support for PostgreSQL MATERIALIZED/NOT MATERIALIZED hints
|
|
27
|
-
- **JSON-to-TypeScript type transformation** - Automatically convert JSON-ified SQL results (dates as strings, BigInts) back to proper TypeScript types with configurable transformation rules
|
|
28
|
-
- **All-in-one dynamic query building with `DynamicQueryBuilder`** - combines filtering, sorting, pagination, and JSON serialization in a single, type-safe interface
|
|
29
|
-
- Dynamic SQL parameter injection for building flexible search queries with `SqlParamInjector` (supports like, ilike, in, any, range queries, OR/AND conditions and more)
|
|
30
|
-
- Dynamic ORDER BY clause injection with `SqlSortInjector` for flexible sorting with support for ASC/DESC, NULLS positioning, and append mode
|
|
31
|
-
- Dynamic LIMIT/OFFSET pagination injection with `SqlPaginationInjector` for efficient data pagination with page-based and offset-based support
|
|
32
|
-
- Type-safe schema management and JSON mapping conversion with full TypeScript support
|
|
33
|
-
- Static query validation and regression testing against your database schema with `SqlSchemaValidator`, enabling early error detection and robust unit tests for schema changes.
|
|
34
|
-
|
|
35
|
-
',borderColor:'rgba(54,162,235,1)',borderWidth:1},{label:'node-sql-parser',data:[0.210,0.223,0.420,0.871],backgroundColor:'rgba(255,206,86,0.8)',borderColor:'rgba(255,206,86,1)',borderWidth:1},{label:'sql-formatter',data:[0.228,0.547,1.057,1.906],backgroundColor:'rgba(255,99,132,0.8)',borderColor:'rgba(255,99,132,1)',borderWidth:1}]},options:{plugins:{legend:{labels:{color:'black'}}},scales:{x:{ticks:{color:'black'}},y:{ticks:{color:'black'}}},backgroundColor:'white'}}&width=700&height=450)
|
|
36
|
-
|
|
37
|
-
> [!Note]
|
|
38
|
-
> The "Mean" column represents the average time taken to process a query. Lower values indicate faster performance. For more details, see the [Benchmark](#benchmarks).
|
|
39
|
-
|
|
40
|
-
## Browser & CDN Ready
|
|
41
|
-
|
|
42
|
-
You can use rawsql-ts directly in modern browsers via CDN (unpkg/jsdelivr)!
|
|
43
|
-
No Node.js dependencies, no build tools required.
|
|
44
|
-
Just import it like this:
|
|
45
|
-
|
|
46
|
-
```html
|
|
47
|
-
<!-- Always get the latest version -->
|
|
48
|
-
<script type="module">
|
|
49
|
-
import { parse } from "https://unpkg.com/rawsql-ts/dist/esm/index.min.js";
|
|
50
|
-
</script>
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
```html
|
|
54
|
-
<!-- Pin a specific version for stability -->
|
|
55
|
-
<script type="module">
|
|
56
|
-
import { parse } from "https://unpkg.com/rawsql-ts@0.10.9-beta/dist/esm/index.min.js";
|
|
57
|
-
</script>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## Installation
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
npm install rawsql-ts
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## Quick Start
|
|
71
|
-
|
|
72
|
-
Experience the power of rawsql-ts with `DynamicQueryBuilder` - build complex queries with filtering, sorting, pagination, and JSON serialization in one go!
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
import { DynamicQueryBuilder, SqlFormatter } from 'rawsql-ts';
|
|
76
|
-
|
|
77
|
-
// Start with a simple base SQL
|
|
78
|
-
const baseSql = 'SELECT id, name, email, created_at FROM users WHERE active = true';
|
|
79
|
-
|
|
80
|
-
// Build a complete dynamic query with all features
|
|
81
|
-
const builder = new DynamicQueryBuilder();
|
|
82
|
-
const query = builder.buildQuery(baseSql, {
|
|
83
|
-
// Dynamic filtering
|
|
84
|
-
filter: {
|
|
85
|
-
status: 'premium',
|
|
86
|
-
created_at: { '>': '2024-01-01' }
|
|
87
|
-
},
|
|
88
|
-
// Dynamic sorting
|
|
89
|
-
sort: {
|
|
90
|
-
created_at: { desc: true },
|
|
91
|
-
name: { asc: true }
|
|
92
|
-
},
|
|
93
|
-
// Dynamic pagination
|
|
94
|
-
paging: {
|
|
95
|
-
page: 2,
|
|
96
|
-
pageSize: 10
|
|
97
|
-
},
|
|
98
|
-
// JSON serialization (optional)
|
|
99
|
-
serialize: {
|
|
100
|
-
rootName: 'user',
|
|
101
|
-
rootEntity: {
|
|
102
|
-
id: 'user',
|
|
103
|
-
name: 'User',
|
|
104
|
-
columns: { id: 'id', name: 'name', email: 'email', createdAt: 'created_at' }
|
|
105
|
-
},
|
|
106
|
-
nestedEntities: []
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// Format and execute
|
|
111
|
-
const formatter = new SqlFormatter();
|
|
112
|
-
const { formattedSql, params } = formatter.format(query);
|
|
113
|
-
|
|
114
|
-
console.log('Generated SQL:');
|
|
115
|
-
console.log(formattedSql);
|
|
116
|
-
// Output: Optimized PostgreSQL JSON query with filtering, sorting, and pagination
|
|
117
|
-
|
|
118
|
-
console.log('Parameters:');
|
|
119
|
-
console.log(params);
|
|
120
|
-
// Output: { status: 'premium', created_at_gt: '2024-01-01' }
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## CTE Management API
|
|
126
|
-
|
|
127
|
-
The CTE Management API provides programmatic control over Common Table Expressions (CTEs), allowing you to build and manipulate WITH clauses dynamically. This is particularly useful for building complex analytical queries, data transformation pipelines, and hierarchical data structures.
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
import { SelectQueryParser, SqlFormatter } from 'rawsql-ts';
|
|
131
|
-
|
|
132
|
-
// Build a multi-step data pipeline with CTEs
|
|
133
|
-
const pipeline = SelectQueryParser.parse('SELECT * FROM final_results').toSimpleQuery();
|
|
134
|
-
|
|
135
|
-
// Step 1: Add raw data CTE with PostgreSQL MATERIALIZED hint
|
|
136
|
-
const salesData = SelectQueryParser.parse(`
|
|
137
|
-
SELECT customer_id, order_date, amount, product_category
|
|
138
|
-
FROM sales WHERE order_date >= '2024-01-01'
|
|
139
|
-
`);
|
|
140
|
-
pipeline.addCTE('raw_sales', salesData.toSimpleQuery(), { materialized: true });
|
|
141
|
-
|
|
142
|
-
// Step 2: Add aggregation CTE
|
|
143
|
-
const monthlyStats = SelectQueryParser.parse(`
|
|
144
|
-
SELECT customer_id, DATE_TRUNC('month', order_date) as month,
|
|
145
|
-
SUM(amount) as total, COUNT(*) as orders
|
|
146
|
-
FROM raw_sales
|
|
147
|
-
GROUP BY customer_id, DATE_TRUNC('month', order_date)
|
|
148
|
-
`);
|
|
149
|
-
pipeline.addCTE('monthly_stats', monthlyStats.toSimpleQuery());
|
|
150
|
-
|
|
151
|
-
// Manage CTEs programmatically
|
|
152
|
-
console.log(pipeline.getCTENames()); // ['raw_sales', 'monthly_stats']
|
|
153
|
-
console.log(pipeline.hasCTE('raw_sales')); // true
|
|
154
|
-
|
|
155
|
-
// Replace the final query to use the CTEs
|
|
156
|
-
const finalQuery = SelectQueryParser.parse(`
|
|
157
|
-
SELECT * FROM monthly_stats WHERE total > 10000
|
|
158
|
-
`);
|
|
159
|
-
pipeline.replaceCTE('final_results', finalQuery.toSimpleQuery());
|
|
160
|
-
|
|
161
|
-
// Format and execute
|
|
162
|
-
const formatter = new SqlFormatter();
|
|
163
|
-
const { formattedSql } = formatter.format(pipeline);
|
|
164
|
-
// Output: WITH "raw_sales" AS MATERIALIZED (...), "monthly_stats" AS (...) SELECT * FROM monthly_stats WHERE total > 10000
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Key features include:
|
|
168
|
-
- **Dynamic CTE Management**: Add, remove, replace, and query CTEs programmatically
|
|
169
|
-
- **PostgreSQL MATERIALIZED Support**: Control query optimization with MATERIALIZED/NOT MATERIALIZED hints
|
|
170
|
-
- **Type Safety**: Full TypeScript support with error handling for duplicate names and invalid operations
|
|
171
|
-
- **Performance Optimized**: O(1) CTE name lookups for efficient operations
|
|
172
|
-
|
|
173
|
-
For comprehensive examples and advanced usage patterns, see the [CTE Management API Usage Guide](../../docs/usage-guides/cte-management-api-usage-guide.md).
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## SelectQueryParser & Query Types
|
|
178
|
-
|
|
179
|
-
rawsql-ts provides robust parsers for `SELECT`, `INSERT`, and `UPDATE` statements, automatically handling SQL comments and providing detailed error messages. By converting SQL into a generic Abstract Syntax Tree (AST), it enables a wide variety of transformation processes.
|
|
180
|
-
|
|
181
|
-
### Query Type Overview
|
|
182
|
-
|
|
183
|
-
The parser returns different query types based on SQL structure:
|
|
184
|
-
|
|
185
|
-
- **`SimpleSelectQuery`**: Single SELECT statement with comprehensive manipulation API
|
|
186
|
-
- **`BinarySelectQuery`**: Combined queries using UNION, INTERSECT, EXCEPT operators
|
|
187
|
-
- **`ValuesQuery`**: VALUES clause queries for data insertion or testing
|
|
188
|
-
- **`SelectQuery`**: Base interface implemented by all SELECT query classes
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
import { SelectQueryParser } from 'rawsql-ts';
|
|
192
|
-
|
|
193
|
-
// Returns SimpleSelectQuery
|
|
194
|
-
const simpleQuery = SelectQueryParser.parse('SELECT id, name FROM products WHERE category = \'electronics\'');
|
|
195
|
-
|
|
196
|
-
// Returns BinarySelectQuery
|
|
197
|
-
const unionQuery = SelectQueryParser.parse('SELECT id, name FROM products UNION SELECT id, name FROM archived_products');
|
|
198
|
-
|
|
199
|
-
// Returns ValuesQuery
|
|
200
|
-
const valuesQuery = SelectQueryParser.parse('VALUES (1, \'Alice\'), (2, \'Bob\')');
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### SimpleSelectQuery - Rich Programmatic API
|
|
204
|
-
|
|
205
|
-
`SimpleSelectQuery` provides extensive methods for programmatic query building and manipulation:
|
|
206
|
-
|
|
207
|
-
**Dynamic Condition Building:**
|
|
208
|
-
- `appendWhereExpr(columnName, exprBuilder)` - Add conditions by column name with upstream injection support
|
|
209
|
-
- `appendWhereRaw()`, `appendHavingRaw()` - Append raw SQL conditions
|
|
210
|
-
- `setParameter(name, value)` - Manage named parameters directly on the query object
|
|
211
|
-
|
|
212
|
-
**Query Composition:**
|
|
213
|
-
- `toUnion()`, `toIntersect()`, `toExcept()` - Combine with other queries
|
|
214
|
-
- `innerJoin()`, `leftJoin()`, `rightJoin()` - Add JOIN clauses programmatically
|
|
215
|
-
- `appendWith()` - Add Common Table Expressions (CTEs)
|
|
216
|
-
|
|
217
|
-
**Advanced Features:**
|
|
218
|
-
- Column-aware condition injection that resolves aliases and expressions
|
|
219
|
-
- Parameter management with validation and type safety
|
|
220
|
-
- Subquery wrapping with `toSource(alias)` for complex compositions
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
import { SelectQueryParser } from 'rawsql-ts';
|
|
224
|
-
|
|
225
|
-
const query = SelectQueryParser.parse('SELECT id, salary * 1.1 AS adjusted_salary FROM employees');
|
|
226
|
-
|
|
227
|
-
// Add condition targeting the calculated column
|
|
228
|
-
query.appendWhereExpr('adjusted_salary', expr => `${expr} > 50000`);
|
|
229
|
-
|
|
230
|
-
// Set parameters directly on the query
|
|
231
|
-
query.setParameter('dept_id', 123);
|
|
232
|
-
|
|
233
|
-
// Add JOINs programmatically
|
|
234
|
-
query.leftJoinRaw('departments', 'd', 'department_id');
|
|
235
|
-
|
|
236
|
-
// Combine with another query
|
|
237
|
-
const adminQuery = SelectQueryParser.parse('SELECT id, salary FROM admins');
|
|
238
|
-
const combinedQuery = query.toUnion(adminQuery);
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
For comprehensive API documentation and advanced examples, see the [SimpleSelectQuery Usage Guide](../../docs/usage-guides/class-SimpleSelectQuery-usage-guide.md).
|
|
242
|
-
|
|
243
|
-
For SelectQueryParser details, see the [SelectQueryParser Usage Guide](../../docs/usage-guides/class-SelectQueryParser-usage-guide.md).
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## SqlFormatter Features
|
|
248
|
-
|
|
249
|
-
The `SqlFormatter` class is the recommended way to format SQL queries, offering advanced capabilities like indentation, keyword casing, multi-line formatting, and comprehensive comment preservation.
|
|
250
|
-
It also allows for detailed style customization. For example, you can define your own formatting rules:
|
|
251
|
-
|
|
252
|
-
```typescript
|
|
253
|
-
import { SelectQueryParser, SqlFormatter } from 'rawsql-ts';
|
|
254
|
-
|
|
255
|
-
const customStyle = {
|
|
256
|
-
identifierEscape: "none",
|
|
257
|
-
parameterSymbol: ":",
|
|
258
|
-
parameterStyle: "named",
|
|
259
|
-
indentSize: 4,
|
|
260
|
-
indentChar: "space",
|
|
261
|
-
newline: "lf",
|
|
262
|
-
keywordCase: "lower",
|
|
263
|
-
commaBreak: "before",
|
|
264
|
-
andBreak: "before",
|
|
265
|
-
orBreak: "before"
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const sqlToFormat = `SELECT u.user_id, u.user_name FROM users as u WHERE status = :active ORDER BY created_at DESC;`;
|
|
269
|
-
const queryToFormat = SelectQueryParser.parse(sqlToFormat);
|
|
270
|
-
const customFormatter = new SqlFormatter(customStyle);
|
|
271
|
-
const { formattedSql: customFormattedSql } = customFormatter.format(queryToFormat);
|
|
272
|
-
|
|
273
|
-
console.log(customFormattedSql);
|
|
274
|
-
/*
|
|
275
|
-
select
|
|
276
|
-
u.user_id
|
|
277
|
-
, u.user_name
|
|
278
|
-
from
|
|
279
|
-
users as u
|
|
280
|
-
where
|
|
281
|
-
status = :active
|
|
282
|
-
order by
|
|
283
|
-
created_at desc;
|
|
284
|
-
*/
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Comment Handling
|
|
288
|
-
|
|
289
|
-
SqlFormatter provides comprehensive comment parsing and export capabilities:
|
|
290
|
-
|
|
291
|
-
```typescript
|
|
292
|
-
import { SqlFormatter } from 'rawsql-ts';
|
|
293
|
-
|
|
294
|
-
// Enable comment export (disabled by default for backward compatibility)
|
|
295
|
-
const formatter = new SqlFormatter({
|
|
296
|
-
exportComment: 'full',
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
const sqlWithComments = `
|
|
300
|
-
-- This is a query to get active users
|
|
301
|
-
SELECT
|
|
302
|
-
u.id,
|
|
303
|
-
u.name /* User's full name */
|
|
304
|
-
FROM users u
|
|
305
|
-
WHERE u.active = true -- Only active users
|
|
306
|
-
`;
|
|
307
|
-
|
|
308
|
-
const query = SelectQueryParser.parse(sqlWithComments);
|
|
309
|
-
const { formattedSql } = formatter.format(query);
|
|
310
|
-
|
|
311
|
-
console.log(formattedSql);
|
|
312
|
-
// Output includes comments preserved as block comments for SQL safety
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
**Comment Features:**
|
|
316
|
-
- **Full Comment Parsing**: Supports both `--` line comments and `/* */` block comments
|
|
317
|
-
- **AST Preservation**: Comments are stored in the Abstract Syntax Tree and preserved throughout transformations
|
|
318
|
-
- **Safe Export**: Line comments are automatically converted to block comments during export to prevent SQL structure issues
|
|
319
|
-
- **Configurable Export**: Choose `exportComment` = "full", "none", "header-only" (only header annotations), or "top-header-only" (outermost header only) to control comment emission
|
|
320
|
-
- **Comment Editing API**: Programmatically add, edit, delete, and search comments using the `CommentEditor` class
|
|
321
|
-
- **Clause Association**: Comments can be associated with specific SQL clauses and keywords
|
|
322
|
-
|
|
323
|
-
For more details, see the [SqlFormatter Usage Guide](../../docs/usage-guides/class-SqlFormatter-usage-guide.md).
|
|
324
|
-
|
|
325
|
-
---
|
|
326
|
-
|
|
327
|
-
## SqlParamInjector Features
|
|
328
|
-
|
|
329
|
-
The `SqlParamInjector` class revolutionizes how you build dynamic search queries. Instead of manually constructing different SQL statements for various search conditions, you simply provide a fixed base SQL and a state object. `SqlParamInjector` then dynamically injects parameters and automatically generates the optimal WHERE conditions.
|
|
330
|
-
|
|
331
|
-
Key benefits include:
|
|
332
|
-
- **Simplified Query Management**: Prepare a single base SQL; `SqlParamInjector` handles the variations.
|
|
333
|
-
- **Effortless Optimal Queries**: Just pass a state object, and it generates a highly efficient query.
|
|
334
|
-
- **Performance-Oriented**: Conditions are intelligently inserted as close to the data source as possible, significantly improving query performance by filtering data early.
|
|
335
|
-
- **Zero Conditional Logic in Code**: Forget writing complex IF statements in your application code to handle different filters.
|
|
336
|
-
- **Enhanced SQL Reusability**: Your base SQL remains clean and can be reused across different scenarios with varying search criteria.
|
|
337
|
-
- **Rich Operator Support**: Supports various SQL operators including equality, comparison, range (min/max), pattern matching (like/ilike), IN clauses, and PostgreSQL array operators.
|
|
338
|
-
- **Advanced Condition Logic**: Supports OR/AND conditions, automatic parentheses grouping, and explicit column mapping for flexible query construction.
|
|
339
|
-
|
|
340
|
-
```typescript
|
|
341
|
-
import { SqlParamInjector, SqlFormatter } from 'rawsql-ts';
|
|
342
|
-
|
|
343
|
-
const sql = `SELECT u.user_id, u.user_name FROM users as u WHERE u.active = TRUE`;
|
|
344
|
-
const injector = new SqlParamInjector();
|
|
345
|
-
// Inject parameters and generate WHERE conditions
|
|
346
|
-
const injectedQuery = injector.inject(sql, { user_id: 42, user_name: 'Alice' });
|
|
347
|
-
|
|
348
|
-
const formatter = new SqlFormatter();
|
|
349
|
-
const { formattedSql, params } = formatter.format(injectedQuery);
|
|
350
|
-
|
|
351
|
-
console.log(formattedSql);
|
|
352
|
-
// Output: select "u"."user_id", "u"."user_name" from "users" as "u" where "u"."active" = true and "u"."user_id" = :user_id and "u"."user_name" = :user_name
|
|
353
|
-
console.log(params);
|
|
354
|
-
// Output: { user_id: 42, user_name: 'Alice' }
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
For more details, see the [SqlParamInjector Usage Guide](../../docs/usage-guides/class-SqlParamInjector-usage-guide.md).
|
|
358
|
-
|
|
359
|
-
---
|
|
360
|
-
|
|
361
|
-
## SqlSortInjector Features
|
|
362
|
-
|
|
363
|
-
The `SqlSortInjector` class enables dynamic ORDER BY clause injection into SQL queries, providing a clean and flexible way to handle sorting requirements. Instead of manually constructing different SQL statements for various sorting scenarios, you can inject sort conditions into your base SQL query, making your code more maintainable and reusable.
|
|
364
|
-
|
|
365
|
-
Key benefits include:
|
|
366
|
-
- **Dynamic Sort Injection**: Add ORDER BY conditions to existing queries without modifying the base SQL
|
|
367
|
-
- **Flexible Sort Options**: Support for ASC/DESC directions with NULLS FIRST/LAST positioning
|
|
368
|
-
- **Append Mode**: Preserves existing ORDER BY clauses and appends new conditions
|
|
369
|
-
- **Column Alias Support**: Works seamlessly with column aliases and calculated expressions
|
|
370
|
-
- **TableColumnResolver Integration**: Supports wildcard SELECT queries through schema resolution
|
|
371
|
-
- **Clean Separation**: Remove existing ORDER BY clauses when needed with `removeOrderBy()`
|
|
372
|
-
|
|
373
|
-
```typescript
|
|
374
|
-
import { SqlSortInjector, SqlFormatter } from 'rawsql-ts';
|
|
375
|
-
|
|
376
|
-
// Basic sort injection
|
|
377
|
-
const baseSql = 'SELECT id, name, created_at FROM users WHERE active = true';
|
|
378
|
-
const sortConditions = {
|
|
379
|
-
created_at: { desc: true, nullsLast: true },
|
|
380
|
-
name: { asc: true }
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
const injector = new SqlSortInjector();
|
|
384
|
-
const sortedQuery = injector.inject(baseSql, sortConditions);
|
|
385
|
-
|
|
386
|
-
const formatter = new SqlFormatter();
|
|
387
|
-
const { formattedSql } = formatter.format(sortedQuery);
|
|
388
|
-
|
|
389
|
-
console.log(formattedSql);
|
|
390
|
-
// Output: select "id", "name", "created_at" from "users" where "active" = true order by "created_at" desc nulls last, "name"
|
|
391
|
-
|
|
392
|
-
// Append to existing ORDER BY
|
|
393
|
-
const existingSql = 'SELECT id, name FROM users ORDER BY id ASC';
|
|
394
|
-
const additionalSort = { name: { desc: true } };
|
|
395
|
-
const appendedQuery = injector.inject(existingSql, additionalSort);
|
|
396
|
-
// Result: SELECT id, name FROM users ORDER BY id ASC, name DESC
|
|
397
|
-
|
|
398
|
-
// Remove existing ORDER BY when needed
|
|
399
|
-
const cleanQuery = SqlSortInjector.removeOrderBy(existingSql);
|
|
400
|
-
const newSortedQuery = injector.inject(cleanQuery, { name: { desc: true } });
|
|
401
|
-
// Result: SELECT id, name FROM users ORDER BY name DESC
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
For more details, see the [SqlSortInjector Usage Guide](../../docs/usage-guides/class-SqlSortInjector-usage-guide.md).
|
|
405
|
-
|
|
406
|
-
---
|
|
407
|
-
|
|
408
|
-
## SqlPaginationInjector Features
|
|
409
|
-
|
|
410
|
-
The `SqlPaginationInjector` class enables dynamic LIMIT/OFFSET clause injection into SQL queries, providing a clean and efficient way to handle data pagination. Instead of manually constructing different SQL statements for various page sizes and offsets, you can inject pagination into your base SQL query, making your code more maintainable and performance-optimized.
|
|
411
|
-
|
|
412
|
-
Key benefits include:
|
|
413
|
-
- **Page-Based Pagination**: Simple page number and page size configuration with automatic offset calculation
|
|
414
|
-
- **Automatic OFFSET Optimization**: Smart handling where page 1 omits unnecessary OFFSET 0 clauses
|
|
415
|
-
- **Existing Clause Detection**: Prevents conflicts by detecting and reporting existing LIMIT/OFFSET clauses
|
|
416
|
-
- **Validation & Safety**: Built-in validation for page numbers, page sizes, and configurable maximum limits
|
|
417
|
-
- **Clean Removal**: Remove existing pagination clauses when needed with `removePagination()`
|
|
418
|
-
- **Performance Conscious**: Generates standard LIMIT/OFFSET patterns optimized for database engines
|
|
419
|
-
|
|
420
|
-
```typescript
|
|
421
|
-
import { SqlPaginationInjector, SqlFormatter } from 'rawsql-ts';
|
|
422
|
-
|
|
423
|
-
// Basic pagination injection
|
|
424
|
-
const baseSql = 'SELECT id, name, email FROM users WHERE active = true ORDER BY created_at DESC';
|
|
425
|
-
const pagination = {
|
|
426
|
-
page: 2, // Page number (1-based)
|
|
427
|
-
pageSize: 20 // Items per page
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
const injector = new SqlPaginationInjector();
|
|
431
|
-
const paginatedQuery = injector.inject(baseSql, pagination);
|
|
432
|
-
|
|
433
|
-
const formatter = new SqlFormatter();
|
|
434
|
-
const { formattedSql } = formatter.format(paginatedQuery);
|
|
435
|
-
|
|
436
|
-
console.log(formattedSql);
|
|
437
|
-
// Output: select "id", "name", "email" from "users" where "active" = true order by "created_at" desc limit 20 offset 20
|
|
438
|
-
|
|
439
|
-
// First page optimization (no OFFSET needed)
|
|
440
|
-
const firstPagePagination = { page: 1, pageSize: 10 };
|
|
441
|
-
const firstPageQuery = injector.inject(baseSql, firstPagePagination);
|
|
442
|
-
const { formattedSql: firstPageSql } = formatter.format(firstPageQuery);
|
|
443
|
-
console.log(firstPageSql);
|
|
444
|
-
// Output: select "id", "name", "email" from "users" where "active" = true order by "created_at" desc limit 10
|
|
445
|
-
|
|
446
|
-
// Remove existing pagination when needed
|
|
447
|
-
const existingPaginatedSql = 'SELECT id, name FROM users LIMIT 50 OFFSET 100';
|
|
448
|
-
const cleanQuery = SqlPaginationInjector.removePagination(existingPaginatedSql);
|
|
449
|
-
const newPagination = { page: 1, pageSize: 25 };
|
|
450
|
-
const repaginatedQuery = injector.inject(cleanQuery, newPagination);
|
|
451
|
-
// Result: Clean query with new pagination applied
|
|
452
|
-
|
|
453
|
-
// Combine with other injectors for complete query building
|
|
454
|
-
let query = new SqlParamInjector().inject(baseSql, { status: 'active' });
|
|
455
|
-
query = new SqlSortInjector().inject(query, { created_at: { desc: true } });
|
|
456
|
-
query = new SqlPaginationInjector().inject(query, { page: 3, pageSize: 15 });
|
|
457
|
-
// Result: Filtered, sorted, and paginated query ready for execution
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
For more details, see the [SqlPaginationInjector Usage Guide](../../docs/usage-guides/class-SqlPaginationInjector-usage-guide.md).
|
|
461
|
-
|
|
462
|
-
---
|
|
463
|
-
|
|
464
|
-
## SelectableColumnCollector Features
|
|
465
|
-
|
|
466
|
-
The `SelectableColumnCollector` class extracts all column references from SQL queries, providing essential metadata for dependency analysis, schema migration, and dynamic query building. It supports both standard column collection and upstream column collection for maximum search conditions in DynamicQuery scenarios.
|
|
467
|
-
|
|
468
|
-
Key benefits include:
|
|
469
|
-
- **Column Dependency Analysis**: Identify all column references used in SQL queries
|
|
470
|
-
- **Schema Migration Support**: Track column usage across complex queries for safe schema changes
|
|
471
|
-
- **DynamicQuery Integration**: Collect maximum available columns for flexible search conditions
|
|
472
|
-
- **Upstream Column Collection**: Gather all columns from CTEs, subqueries, and tables for comprehensive analysis
|
|
473
|
-
- **Duplicate Detection**: Configurable modes for handling duplicate column names (column-only vs table.column)
|
|
474
|
-
- **Security Analysis**: Enable column-level access control by understanding column dependencies
|
|
475
|
-
|
|
476
|
-
```typescript
|
|
477
|
-
import { SelectableColumnCollector, DuplicateDetectionMode } from 'rawsql-ts';
|
|
478
|
-
|
|
479
|
-
const sql = `
|
|
480
|
-
WITH user_stats AS (
|
|
481
|
-
SELECT u.id, u.name, u.email, COUNT(p.id) as post_count
|
|
482
|
-
FROM users u
|
|
483
|
-
LEFT JOIN posts p ON u.id = p.user_id
|
|
484
|
-
GROUP BY u.id, u.name, u.email
|
|
485
|
-
)
|
|
486
|
-
SELECT us.name, us.post_count
|
|
487
|
-
FROM user_stats us
|
|
488
|
-
WHERE us.post_count > 5
|
|
489
|
-
`;
|
|
490
|
-
|
|
491
|
-
const query = SelectQueryParser.parse(sql);
|
|
492
|
-
|
|
493
|
-
// Basic column collection - only referenced columns
|
|
494
|
-
const collector = new SelectableColumnCollector();
|
|
495
|
-
const columns = collector.collect(query);
|
|
496
|
-
console.log(columns.map(c => c.name));
|
|
497
|
-
// Output: ['name', 'post_count']
|
|
498
|
-
|
|
499
|
-
// Upstream collection for DynamicQuery - all available columns
|
|
500
|
-
const upstreamCollector = new SelectableColumnCollector(
|
|
501
|
-
null, false, DuplicateDetectionMode.ColumnNameOnly,
|
|
502
|
-
{ upstream: true }
|
|
503
|
-
);
|
|
504
|
-
const allColumns = upstreamCollector.collect(query);
|
|
505
|
-
console.log(allColumns.map(c => c.name));
|
|
506
|
-
// Output: ['name', 'post_count', 'id', 'email'] // All columns from CTE
|
|
507
|
-
|
|
508
|
-
// Duplicate detection modes
|
|
509
|
-
const fullNameCollector = new SelectableColumnCollector(
|
|
510
|
-
null, false, DuplicateDetectionMode.FullName
|
|
511
|
-
);
|
|
512
|
-
const uniqueColumns = fullNameCollector.collect(query);
|
|
513
|
-
// Distinguishes between u.id and p.id as separate columns
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
### Use Cases
|
|
517
|
-
|
|
518
|
-
- **DynamicQuery Maximum Search Conditions**: Collect all available columns from upstream sources (CTEs, subqueries, tables) to enable comprehensive filtering options
|
|
519
|
-
- **Schema Migration Planning**: Identify all column dependencies before making schema changes
|
|
520
|
-
- **Security Analysis**: Implement column-level access control by understanding which columns are accessed
|
|
521
|
-
- **Query Optimization**: Analyze column usage patterns to optimize query performance
|
|
522
|
-
- **API Generation**: Automatically generate filter and sort options based on available columns
|
|
523
|
-
|
|
524
|
-
---
|
|
525
|
-
|
|
526
|
-
## DynamicQueryBuilder Features
|
|
527
|
-
|
|
528
|
-
The `DynamicQueryBuilder` class is a powerful, all-in-one solution that combines SQL parsing with dynamic condition injection (filtering, sorting, pagination, and JSON serialization). It provides a unified interface for building complex queries without the need to manually chain multiple injectors, making it ideal for modern web applications that require flexible, dynamic query generation.
|
|
529
|
-
|
|
530
|
-
Key benefits include:
|
|
531
|
-
- **Unified Interface**: Single class that combines filtering, sorting, pagination, and JSON serialization
|
|
532
|
-
- **Framework-Agnostic**: Pure JavaScript/TypeScript with no file system dependencies
|
|
533
|
-
- **Composable Architecture**: Internally uses specialized injectors in optimal order for performance
|
|
534
|
-
- **Type-Safe**: Full TypeScript support with strongly typed options and return values
|
|
535
|
-
- **Performance Optimized**: Applies conditions in the most efficient order (filter -> sort -> paginate -> serialize)
|
|
536
|
-
- **Easy Testing**: No external dependencies make unit testing straightforward
|
|
537
|
-
|
|
538
|
-
```typescript
|
|
539
|
-
import { DynamicQueryBuilder, SqlFormatter } from 'rawsql-ts';
|
|
540
|
-
|
|
541
|
-
// Create a builder instance
|
|
542
|
-
const builder = new DynamicQueryBuilder();
|
|
543
|
-
|
|
544
|
-
// Build a complete dynamic query with all features
|
|
545
|
-
const baseQuery = 'SELECT id, name, email, created_at FROM users WHERE active = true';
|
|
546
|
-
const options = {
|
|
547
|
-
filter: {
|
|
548
|
-
status: 'premium',
|
|
549
|
-
created_at: { min: '2024-01-01' } // Range filter
|
|
550
|
-
},
|
|
551
|
-
sort: {
|
|
552
|
-
created_at: { desc: true, nullsLast: true },
|
|
553
|
-
name: { asc: true }
|
|
554
|
-
},
|
|
555
|
-
paging: { page: 2, pageSize: 20 },
|
|
556
|
-
serialize: {
|
|
557
|
-
rootName: 'users',
|
|
558
|
-
rootEntity: {
|
|
559
|
-
id: 'user',
|
|
560
|
-
name: 'User',
|
|
561
|
-
columns: { id: 'id', name: 'name', email: 'email', created: 'created_at' }
|
|
562
|
-
},
|
|
563
|
-
nestedEntities: []
|
|
564
|
-
}
|
|
565
|
-
};
|
|
566
|
-
|
|
567
|
-
const dynamicQuery = builder.buildQuery(baseQuery, options);
|
|
568
|
-
|
|
569
|
-
const formatter = new SqlFormatter();
|
|
570
|
-
const { formattedSql, params } = formatter.format(dynamicQuery);
|
|
571
|
-
|
|
572
|
-
console.log(formattedSql);
|
|
573
|
-
// Output: Complex JSON query with all conditions applied
|
|
574
|
-
console.log(params);
|
|
575
|
-
// Output: { status: 'premium', created_at_min: '2024-01-01', paging_limit: 20, paging_offset: 20 }
|
|
576
|
-
|
|
577
|
-
// Convenience methods for specific use cases
|
|
578
|
-
const filteredOnly = builder.buildFilteredQuery(baseQuery, { name: 'Alice' });
|
|
579
|
-
const sortedOnly = builder.buildSortedQuery(baseQuery, { created_at: { desc: true } });
|
|
580
|
-
const paginatedOnly = builder.buildPaginatedQuery(baseQuery, { page: 1, pageSize: 10 });
|
|
581
|
-
|
|
582
|
-
// Validate SQL without applying modifications
|
|
583
|
-
const isValid = builder.validateSql('SELECT id FROM users');
|
|
584
|
-
console.log(isValid); // true
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
For more details, see the [DynamicQueryBuilder Usage Guide](../../docs/guide/querybuilding-recipes.md).
|
|
1
|
+
# rawsql-ts
|
|
588
2
|
|
|
589
|
-
|
|
3
|
+

|
|
4
|
+

|
|
590
5
|
|
|
591
|
-
|
|
6
|
+
A high-performance SQL parser and AST transformer written in TypeScript. Parse raw SQL into objects, manipulate query structures programmatically, and generate optimized output -- all with zero dependencies.
|
|
592
7
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
const targetTable = 'users';
|
|
751
|
-
const primaryKeys = ['id']; // Column(s) to match records between source and target
|
|
752
|
-
|
|
753
|
-
const updateQuery = QueryBuilder.buildUpdateQuery(
|
|
754
|
-
normalizedSelectQuery,
|
|
755
|
-
'd', // Alias of the source query in the FROM clause
|
|
756
|
-
targetTable,
|
|
757
|
-
primaryKeys
|
|
758
|
-
);
|
|
759
|
-
|
|
760
|
-
const formatter = new SqlFormatter({ preset: 'postgres' }); // Using postgres preset for clarity
|
|
761
|
-
const { formattedSql: updateSql } = formatter.format(updateQuery);
|
|
762
|
-
|
|
763
|
-
console.log(updateSql);
|
|
764
|
-
// Example output (actual output depends on the SQL dialect and specific query structure):
|
|
765
|
-
// update "users" set "email" = "d"."email", "last_login" = "d"."last_login" from (SELECT id, new_email AS email, last_login FROM user_updates_source WHERE needs_update = TRUE) as "d" where "users"."id" = "d"."id"
|
|
766
|
-
```
|
|
767
|
-
|
|
768
|
-
For more details on `QueryBuilder`, see the [QueryBuilder Usage Guide](../../docs/usage-guides/class-QueryBuilder-usage-guide.md).
|
|
769
|
-
|
|
770
|
-
---
|
|
771
|
-
|
|
772
|
-
## SchemaManager Features
|
|
773
|
-
|
|
774
|
-
The `SchemaManager` class provides unified schema definition and type-safe conversion to various formats, eliminating code duplication for rawsql-ts. It serves as a central hub for managing database schema definitions and converting them to formats required by different components like `SqlParamInjector` and `PostgresJsonQueryBuilder`.
|
|
775
|
-
|
|
776
|
-
Key benefits include:
|
|
777
|
-
- **Unified Schema Definition**: Define your database schema once and generate JSON mappings, table column resolvers, and other formats for multiple rawsql-ts components
|
|
778
|
-
- **Type-Safe JSON Mapping**: Fully typed conversion without using `any` types
|
|
779
|
-
- **Schema Validation**: Built-in validation ensures schema consistency and integrity
|
|
780
|
-
- **Relationship Management**: Supports complex table relationships with object and array outputs
|
|
781
|
-
|
|
782
|
-
```typescript
|
|
783
|
-
import { SchemaManager, createSchemaManager } from 'rawsql-ts';
|
|
784
|
-
|
|
785
|
-
// Define your database schema once
|
|
786
|
-
const schemas = {
|
|
787
|
-
users: {
|
|
788
|
-
name: 'users',
|
|
789
|
-
columns: {
|
|
790
|
-
user_id: { name: 'user_id', isPrimaryKey: true },
|
|
791
|
-
user_name: { name: 'user_name' },
|
|
792
|
-
email: { name: 'email' }
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
};
|
|
796
|
-
|
|
797
|
-
// Create SchemaManager and use with other components
|
|
798
|
-
const schemaManager = createSchemaManager(schemas);
|
|
799
|
-
const tableColumnResolver = schemaManager.createTableColumnResolver();
|
|
800
|
-
const injector = new SqlParamInjector({ tableColumnResolver });
|
|
801
|
-
```
|
|
802
|
-
|
|
803
|
-
For more details on `SchemaManager`, see the [SchemaManager Usage Guide](../../docs/usage-guides/class-SchemaManager-usage-guide.md).
|
|
804
|
-
|
|
805
|
-
---
|
|
806
|
-
|
|
807
|
-
## Benchmarks
|
|
808
|
-
|
|
809
|
-
This project includes a comprehensive benchmark suite to evaluate the performance of `rawsql-ts` in comparison with other popular libraries such as `node-sql-parser` and `sql-formatter`.
|
|
810
|
-
|
|
811
|
-
### How to Run
|
|
812
|
-
|
|
813
|
-
```bash
|
|
814
|
-
npm run benchmark
|
|
815
|
-
```
|
|
816
|
-
|
|
817
|
-
### Benchmark Details
|
|
818
|
-
|
|
819
|
-
The benchmark suite measures SQL parsing and formatting speed across queries of varying complexity:
|
|
820
|
-
|
|
821
|
-
- **Tokens20**: Simple SELECT with a basic WHERE clause (~20 tokens)
|
|
822
|
-
- **Tokens70**: Medium complexity query with JOINs and multiple conditions (~70 tokens)
|
|
823
|
-
- **Tokens140**: Complex query with CTEs and aggregations (~140 tokens)
|
|
824
|
-
- **Tokens230**: Highly complex query with multiple CTEs, subqueries, and window functions (~230 tokens)
|
|
825
|
-
|
|
826
|
-
### Benchmark Environment
|
|
827
|
-
|
|
828
|
-
```
|
|
829
|
-
benchmark.js v2.1.4
|
|
830
|
-
Windows 10.0.26100
|
|
831
|
-
AMD Ryzen 7 7800X3D (8C/16T)
|
|
832
|
-
Node.js v22.14.0
|
|
833
|
-
```
|
|
834
|
-
|
|
835
|
-
### Results
|
|
836
|
-
|
|
837
|
-
#### Tokens20
|
|
838
|
-
| Method | Mean (ms) | Error (ms) | StdDev (ms) | Times slower vs rawsql-ts |
|
|
839
|
-
|---------------------------------- |-----------:|----------:|----------:|--------------------------:|
|
|
840
|
-
| rawsql-ts | 0.029 | 0.0087 | 0.0044 | - |
|
|
841
|
-
| node-sql-parser | 0.210 | 0.4505 | 0.2298 | 7.3x |
|
|
842
|
-
| sql-formatter | 0.228 | 0.1598 | 0.0815 | 8.0x |
|
|
843
|
-
|
|
844
|
-
> [!Note] When the token count is extremely low, `rawsql-ts` becomes disproportionately fast. However, such small queries are rare in real-world scenarios, so this result is excluded from the overall performance summary.
|
|
845
|
-
|
|
846
|
-
#### Tokens70
|
|
847
|
-
| Method | Mean (ms) | Error (ms) | StdDev (ms) | Times slower vs rawsql-ts |
|
|
848
|
-
|---------------------------------- |-----------:|----------:|----------:|--------------------------:|
|
|
849
|
-
| rawsql-ts | 0.075 | 0.0541 | 0.0276 | - |
|
|
850
|
-
| node-sql-parser | 0.223 | 0.0848 | 0.0432 | 3.0x |
|
|
851
|
-
| sql-formatter | 0.547 | 0.1432 | 0.0731 | 7.3x |
|
|
852
|
-
|
|
853
|
-
#### Tokens140
|
|
854
|
-
| Method | Mean (ms) | Error (ms) | StdDev (ms) | Times slower vs rawsql-ts |
|
|
855
|
-
|---------------------------------- |-----------:|----------:|----------:|--------------------------:|
|
|
856
|
-
| rawsql-ts | 0.137 | 0.0175 | 0.0089 | - |
|
|
857
|
-
| node-sql-parser | 0.420 | 0.1030 | 0.0526 | 3.1x |
|
|
858
|
-
| sql-formatter | 1.057 | 0.2390 | 0.1220 | 7.7x |
|
|
859
|
-
|
|
860
|
-
#### Tokens230
|
|
861
|
-
| Method | Mean (ms) | Error (ms) | StdDev (ms) | Times slower vs rawsql-ts |
|
|
862
|
-
|---------------------------------- |-----------:|----------:|----------:|--------------------------:|
|
|
863
|
-
| rawsql-ts | 0.239 | 0.0577 | 0.0294 | - |
|
|
864
|
-
| node-sql-parser | 0.871 | 0.2042 | 0.1042 | 3.6x |
|
|
865
|
-
| sql-formatter | 1.906 | 1.4631 | 0.7465 | 8.0x |
|
|
866
|
-
|
|
867
|
-
### Performance Summary
|
|
868
|
-
|
|
869
|
-
- `rawsql-ts` remains one of the fastest parsers, though it is approximately 10% slower in version 0.7 compared to previous versions. This is due to the addition of enhanced parameterized query parsing and SQL formatting capabilities.
|
|
870
|
-
- About 3x faster than `node-sql-parser`.
|
|
871
|
-
- About 4x faster than `sql-parser-cst`.
|
|
872
|
-
- About 7x faster than `sql-formatter`.
|
|
873
|
-
- Maintains high performance even for complex SQL, while providing comprehensive features.
|
|
874
|
-
|
|
875
|
-
> **Note:** These benchmarks are based on a specific hardware and software environment. Actual performance may vary depending on system configuration and query complexity.
|
|
876
|
-
|
|
877
|
-
---
|
|
8
|
+
> [!NOTE]
|
|
9
|
+
> This library is currently in beta. The API may change until the v1.0 release.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Zero dependencies** -- fully self-contained and lightweight
|
|
14
|
+
- **High-performance** -- significantly faster than node-sql-parser in our parse-only benchmarks
|
|
15
|
+
- **Browser ready** -- works in browsers via CDN (unpkg / jsdelivr)
|
|
16
|
+
- **Dynamic query building** -- filtering, sorting, pagination, JSON serialization, and truthful optional-condition pruning
|
|
17
|
+
- **CTE management** -- add, remove, and manipulate CTEs programmatically
|
|
18
|
+
- **Schema validation** -- static query validation against your database schema
|
|
19
|
+
- **Full TypeScript support** -- type-safe APIs throughout
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install rawsql-ts
|
|
25
|
+
````
|
|
26
|
+
|
|
27
|
+
Or use directly in the browser via CDN:
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<script type="module">
|
|
31
|
+
import { parse } from "https://unpkg.com/rawsql-ts/dist/esm/index.min.js";
|
|
32
|
+
</script>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { DynamicQueryBuilder, SqlFormatter } from "rawsql-ts";
|
|
39
|
+
|
|
40
|
+
const baseSql = "SELECT id, name, email, created_at FROM users WHERE active = true";
|
|
41
|
+
|
|
42
|
+
const builder = new DynamicQueryBuilder();
|
|
43
|
+
const query = builder.buildQuery(baseSql, {
|
|
44
|
+
filter: { status: "premium", created_at: { ">": "2024-01-01" } },
|
|
45
|
+
sort: { created_at: { desc: true }, name: { asc: true } },
|
|
46
|
+
paging: { page: 2, pageSize: 10 },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const formatter = new SqlFormatter();
|
|
50
|
+
const { formattedSql, params } = formatter.format(query);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## SSSQL for Optional Conditions
|
|
54
|
+
|
|
55
|
+
When the request is "add an optional filter", rawsql-ts can keep the SQL source truthful instead of pushing you toward string-built `WHERE` assembly.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const sql = `
|
|
59
|
+
SELECT p.product_id, p.product_name
|
|
60
|
+
FROM products p
|
|
61
|
+
WHERE (:brand_name IS NULL OR p.brand_name = :brand_name)
|
|
62
|
+
AND (:category_name IS NULL OR EXISTS (
|
|
63
|
+
SELECT 1
|
|
64
|
+
FROM product_categories pc
|
|
65
|
+
JOIN categories c
|
|
66
|
+
ON c.category_id = pc.category_id
|
|
67
|
+
WHERE pc.product_id = p.product_id
|
|
68
|
+
AND c.category_name = :category_name
|
|
69
|
+
))
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
const builder = new DynamicQueryBuilder();
|
|
73
|
+
const query = builder.buildQuery(sql, {
|
|
74
|
+
optionalConditionParameters: {
|
|
75
|
+
brand_name: null,
|
|
76
|
+
category_name: "shoes",
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
This SSSQL style keeps optionality visible in the SQL itself and lets rawsql-ts prune only the explicitly targeted absent branches.
|
|
82
|
+
Use `DynamicQueryBuilder` filter injection first for optional predicates on columns that already exist in the current query. Reach for SSSQL when the optional filter needs a table or branch that is not already part of the query graph.
|
|
83
|
+
|
|
84
|
+
Read more:
|
|
85
|
+
|
|
86
|
+
- [What Is SSSQL?](../../docs/guide/sssql-overview.md)
|
|
87
|
+
- [SSSQL Optional Branch Pruning MVP](../../docs/guide/sssql-optional-branch-pruning.md)
|
|
88
|
+
- [Querybuilding Recipes](../../docs/guide/querybuilding-recipes.md)
|
|
89
|
+
|
|
90
|
+
## API Overview
|
|
91
|
+
|
|
92
|
+
### Parsing
|
|
93
|
+
|
|
94
|
+
| Class | Description | Docs |
|
|
95
|
+
| ------------------- | -------------------------------- | -------------------------------------------------- |
|
|
96
|
+
| `SelectQueryParser` | Parse SELECT statements into AST | [Guide](../../docs/guide/getting-started.md) |
|
|
97
|
+
| `InsertQueryParser` | Parse INSERT statements into AST | [API](../../docs/api/classes/InsertQueryParser.md) |
|
|
98
|
+
| `UpdateQueryParser` | Parse UPDATE statements into AST | [API](../../docs/api/classes/UpdateQueryParser.md) |
|
|
99
|
+
| `DeleteQueryParser` | Parse DELETE statements into AST | [API](../../docs/api/classes/DeleteQueryParser.md) |
|
|
100
|
+
|
|
101
|
+
### Query Building
|
|
102
|
+
|
|
103
|
+
| Class | Description | Docs |
|
|
104
|
+
| -------------------------- | -------------------------------------------------------------- | --------------------------------------------------------- |
|
|
105
|
+
| `DynamicQueryBuilder` | All-in-one filtering, sorting, pagination, serialization, and SSSQL optional-condition pruning | [Guide](../../docs/guide/querybuilding-recipes.md) |
|
|
106
|
+
| `QueryBuilder` | Convert SELECT queries into INSERT / UPDATE statements | [API](../../docs/api/classes/QueryBuilder.md) |
|
|
107
|
+
| `PostgresJsonQueryBuilder` | Transform relational queries into hierarchical JSON structures | [API](../../docs/api/classes/PostgresJsonQueryBuilder.md) |
|
|
108
|
+
|
|
109
|
+
### Injection
|
|
110
|
+
|
|
111
|
+
| Class | Description | Docs |
|
|
112
|
+
| ----------------------- | -------------------------------------------------------------- | ------------------------------------------------------ |
|
|
113
|
+
| `SqlParamInjector` | Dynamic WHERE condition injection from parameters | [API](../../docs/api/classes/SqlParamInjector.md) |
|
|
114
|
+
| `SqlSortInjector` | Dynamic ORDER BY injection with ASC/DESC and NULLS positioning | [API](../../docs/api/classes/SqlSortInjector.md) |
|
|
115
|
+
| `SqlPaginationInjector` | Dynamic LIMIT/OFFSET injection with page-based support | [API](../../docs/api/classes/SqlPaginationInjector.md) |
|
|
116
|
+
|
|
117
|
+
### Formatting
|
|
118
|
+
|
|
119
|
+
| Class | Description | Docs |
|
|
120
|
+
| -------------- | --------------------------------------------------------------------- | ----------------------------------------------- |
|
|
121
|
+
| `SqlFormatter` | SQL formatting with indentation, keyword casing, and comment handling | [Guide](../../docs/guide/formatting-recipes.md) |
|
|
122
|
+
|
|
123
|
+
### Analysis
|
|
124
|
+
|
|
125
|
+
| Class | Description | Docs |
|
|
126
|
+
| --------------------------- | ----------------------------------------------------- | ---------------------------------------------------------- |
|
|
127
|
+
| `SelectableColumnCollector` | Extract column references for dependency analysis | [API](../../docs/api/classes/SelectableColumnCollector.md) |
|
|
128
|
+
| `SqlSchemaValidator` | Validate queries against a database schema definition | [API](../../docs/api/classes/SqlSchemaValidator.md) |
|
|
129
|
+
| `QueryFlowDiagramGenerator` | Generate Mermaid flow diagrams from SQL queries | [API](../../docs/api/classes/QueryFlowDiagramGenerator.md) |
|
|
130
|
+
|
|
131
|
+
### Schema & CTE
|
|
132
|
+
|
|
133
|
+
| Class | Description | Docs |
|
|
134
|
+
| ------------------- | ---------------------------------------------------------- | -------------------------------------------------- |
|
|
135
|
+
| `SchemaManager` | Unified schema definition with type-safe format conversion | [API](../../docs/api/classes/SchemaManager.md) |
|
|
136
|
+
| `SimpleSelectQuery` | Programmatic CTE management (add, remove, replace) | [API](../../docs/api/classes/SimpleSelectQuery.md) |
|
|
137
|
+
|
|
138
|
+
## Benchmarks
|
|
139
|
+
|
|
140
|
+
This section reports **parse-only** benchmark results for the SQL parser. It measures AST parsing time, not SQL formatting time.
|
|
141
|
+
|
|
142
|
+
For readability, workloads are described by approximate SQL line counts, with token counts included in parentheses for technical precision. Parser cost is driven more directly by token volume than by formatting style.
|
|
143
|
+
|
|
144
|
+
Across these workloads, parsing remains fast and stable, performance remains practical, and no performance cliff was observed up to the very large case.
|
|
145
|
+
|
|
146
|
+
',backgroundColor:'rgba(54,162,235,0.15)',fill:false,tension:0.2},{label:'node-sql-parser',data:[0.687,0.744,1.56,36.52,54.775],borderColor:'rgba(255,206,86,1)',backgroundColor:'rgba(255,206,86,0.15)',fill:false,tension:0.2}]},options:{plugins:{legend:{labels:{color:'black'}}},elements:{point:{radius:3}},scales:{x:{ticks:{color:'black'}},y:{ticks:{color:'black'}}},backgroundColor:'white'}}&width=760&height=420)
|
|
147
|
+
|
|
148
|
+
| Workload | rawsql-ts | node-sql-parser |
|
|
149
|
+
|----------|----------:|----------------:|
|
|
150
|
+
| Small query, about 8 lines (70 tokens) | 0.040 ms | 0.687 ms (17.0x) |
|
|
151
|
+
| Medium query, about 12 lines (140 tokens) | 0.080 ms | 0.744 ms (9.3x) |
|
|
152
|
+
| Large query, about 20 lines (230 tokens) | 0.168 ms | 1.560 ms (9.3x) |
|
|
153
|
+
| Mid-large query, about 400-500 lines (5,000 tokens) | 4.438 ms | 36.520 ms (8.2x) |
|
|
154
|
+
| Very large query, about 1,000+ lines (~12,000 tokens) | 8.173 ms | 54.775 ms (6.7x) |
|
|
155
|
+
|
|
156
|
+
> Benchmarked on AMD Ryzen 7 7800X3D / Node.js v22.14.0 / node-sql-parser 5.4.0 (2026-03-06). The mid-large and very large cases use benchmark-only analytics-style SQL workloads that represent practical long-query classes rather than formatter scenarios. See [benchmark details](../../docs/bench/parse-benchmark.md) for full results.
|
|
157
|
+
|
|
158
|
+
## Online Demo
|
|
159
|
+
|
|
160
|
+
[Try rawsql-ts in your browser](https://mk3008.github.io/rawsql-ts/)
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT
|
|
878
165
|
|
|
879
|
-
Feel free to try rawsql-ts! Questions, requests, and bug reports are always welcome.
|