Skip to content

Commit 85646c4

Browse files
authored
Update README.md
1 parent 3cd4ead commit 85646c4

File tree

1 file changed

+157
-21
lines changed

1 file changed

+157
-21
lines changed

README.md

Lines changed: 157 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,166 @@
11
# CarbunqleX - SQL Parser and Modeler
22

3-
**CarbunqleX** dramatically improves the reusability and maintainability of RawSQL.
3+
![GitHub](https://img.shields.io/github/license/mk3008/Carbunqlex)
4+
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/mk3008/Carbunqlex)
5+
![Github Last commit](https://img.shields.io/github/last-commit/mk3008/Carbunqlex)
6+
[![Carbunqlex](https://img.shields.io/nuget/v/Carbunqlex.svg)](https://www.nuget.org/packages/Carbunqlex/)
7+
[![Carbunqlex](https://img.shields.io/nuget/dt/Carbunqlex.svg)](https://www.nuget.org/packages/Carbunqlex/)
48

5-
By deeply analyzing the AST of RawSQL—including subqueries and CTEs—it enables advanced query modifications while preserving semantic integrity. With CarbunqleX, you can:
6-
- Overwrite selection columns
7-
- Insert `JOIN` and `WHERE` conditions
8-
- Transform queries into various SQL statements (`CREATE TABLE AS`, `INSERT INTO`, `UPDATE`, `DELETE`)
9+
## 🚀 Overview
910

10-
## 🚀 Advanced CTE Handling
11-
One of CarbunqleX's most powerful features is its **flexible handling of CTEs**.
12-
Normally, CTEs are limited to the `WITH` clause and cannot be directly referenced in `WHERE` or `JOIN` conditions.
13-
However, CarbunqleX detects existing CTEs and **lifts them to the top level**, allowing seamless inclusion in conditions where they would otherwise be invalid.
14-
This enables highly dynamic and reusable query transformations.
11+
**CarbunqleX** enhances the reusability and maintainability of raw SQL queries by deeply analyzing their Abstract Syntax Tree (AST). This allows for powerful transformations while preserving query semantics. With CarbunqleX, you can:
1512

16-
## 💥 Easy Insertion of Search Conditions
17-
Another standout feature of CarbunqleX is its **ease of inserting search conditions**.
18-
With AST parsing, the library automatically identifies the most effective point for insertion, such as within subqueries or CTEs, ensuring that the conditions are applied optimally.
13+
- Modify selection columns
14+
- Inject `JOIN` and `WHERE` conditions dynamically
15+
- Transform queries into different SQL statements (`CREATE TABLE AS`, `INSERT INTO`, `UPDATE`, `DELETE`)
1916

20-
Unlike general libraries where you have to manually specify where to insert search conditions (usually at the top level of the query), CarbunqleX **automatically detects** the deepest relevant level of the query and inserts conditions at that level.
21-
For instance, when dealing with a `GROUP BY` query, it's crucial to insert search conditions **before** the grouping to ensure they are effective. CarbunqleX handles this seamlessly without you needing to worry about the hierarchical structure of the query!
17+
## 💡 Key Features
2218

23-
## 🔥 Lightweight & Easy to Use
24-
- **Minimal dependencies** – Works directly with RawSQL
25-
- **No special setup or DBMS required** – Operates purely on query strings
26-
- **Seamless integration** – Works alongside general ORM libraries
19+
### Advanced CTE Handling
2720

28-
---
21+
CarbunqleX offers **flexible Common Table Expression (CTE) processing**. Traditionally, CTEs exist only within the `WITH` clause and cannot be referenced in `WHERE` or `JOIN` conditions. However, CarbunqleX detects existing CTEs and **lifts them to the top level**, making them accessible in places where they would otherwise be restricted. This enables highly flexible query modifications.
2922

30-
**Let's make RawSQL more powerful and reusable with CarbunqleX!**
23+
### Intelligent Search Condition Injection
24+
25+
Unlike conventional SQL libraries, CarbunqleX automatically determines the most appropriate insertion point for search conditions, even within complex queries involving subqueries and CTEs. This ensures optimal filtering while preserving query integrity. For example, when dealing with `GROUP BY`, conditions are inserted **before** aggregation to ensure correctness.
26+
27+
### Lightweight and Easy to Use
28+
29+
- **Minimal dependencies** – Works directly with raw SQL
30+
- **No special setup or DBMS required** – Purely operates on query strings
31+
- **Seamless ORM integration** – Works alongside existing ORM frameworks
32+
33+
## 📦 Installation
34+
35+
To install [Carbunqlex](https://www.nuget.org/packages/Carbunqlex/), use the following command:
36+
37+
```sh
38+
PM> NuGet\Install-Package Carbunqlex
39+
```
40+
41+
## 📖 Documentation
42+
43+
### 1️⃣ Parsing a SQL Query
44+
45+
Let's start by parsing a simple SQL query into an AST using `QueryAstParser.Parse`. We will then convert it back to SQL with `ToSql` and inspect its structure using `ToTreeString`.
46+
47+
```csharp
48+
using Carbunqlex;
49+
using Carbunqlex.Parsing;
50+
51+
var sql = "SELECT a.table_a_id, a.value FROM table_a AS a";
52+
var query = QueryAstParser.Parse(sql);
53+
54+
// Convert back to SQL
55+
Console.WriteLine("* SQL");
56+
Console.WriteLine(query.ToSql());
57+
58+
// View AST structure (useful for debugging)
59+
Console.WriteLine("* AST");
60+
Console.WriteLine(query.ToTreeString());
61+
```
62+
63+
This basic example demonstrates how CarbunqleX converts SQL into a structured AST representation, making it easier to analyze and manipulate queries programmatically.
64+
65+
### 2️⃣ Modifying the WHERE Clause
66+
67+
Now, let's modify the query by injecting a `WHERE` condition.
68+
69+
```csharp
70+
var query = QueryAstParser.Parse("SELECT a.table_a_id, a.value FROM table_a AS a");
71+
72+
// Inject a filter condition
73+
query.Where("value", w => w.Equal(1));
74+
75+
Console.WriteLine(query.ToSql());
76+
```
77+
78+
#### 🔍 Expected SQL Output
79+
80+
```sql
81+
SELECT a.table_a_id, a.value
82+
FROM table_a AS a
83+
WHERE a.value = 1;
84+
```
85+
86+
CarbunqleX automatically determines where to insert the condition while maintaining SQL integrity.
87+
88+
### 3️⃣ Handling CTEs and Subqueries
89+
90+
Let's take it a step further by injecting a `WHERE` condition into a query that includes **CTEs and subqueries**.
91+
92+
```csharp
93+
var query = QueryAstParser.Parse("""
94+
WITH regional_sales AS (
95+
SELECT orders.region, SUM(orders.amount) AS total_sales
96+
FROM orders
97+
GROUP BY orders.region
98+
), top_regions AS (
99+
SELECT rs.region
100+
FROM regional_sales rs
101+
WHERE rs.total_sales > (SELECT SUM(x.total_sales)/10 FROM regional_sales x)
102+
)
103+
SELECT orders.region, orders.product, SUM(orders.quantity) AS product_units, SUM(orders.amount) AS product_sales
104+
FROM orders
105+
WHERE orders.region IN (SELECT x.region FROM top_regions x)
106+
GROUP BY orders.region, orders.product
107+
""");
108+
109+
query.Where("region", w => w.Equal("'east'"));
110+
```
111+
112+
#### 🔍 Modified SQL Output
113+
114+
```sql
115+
WITH regional_sales AS (
116+
SELECT orders.region, SUM(orders.amount) AS total_sales
117+
FROM orders
118+
WHERE orders.region = 'east'
119+
GROUP BY orders.region
120+
),
121+
top_regions AS (
122+
SELECT rs.region
123+
FROM regional_sales rs
124+
WHERE rs.total_sales > (SELECT SUM(x.total_sales)/10 FROM regional_sales x)
125+
)
126+
SELECT orders.region, orders.product, SUM(orders.quantity) AS product_units, SUM(orders.amount) AS product_sales
127+
FROM orders
128+
WHERE orders.region IN (SELECT x.region FROM top_regions x)
129+
GROUP BY orders.region, orders.product;
130+
```
131+
132+
CarbunqleX **intelligently places the condition in the deepest relevant query**, ensuring correctness.
133+
134+
### 4️⃣ Advanced Filtering
135+
136+
Now, let's introduce a **more advanced use case** where we dynamically filter data based on user permissions. We'll define a reusable function to retrieve regions a user has access to and use it in a filtering condition.
137+
138+
#### 🔧 Define a Subquery Function
139+
140+
```csharp
141+
private QueryNode BuildRegionScalarQueryByUser(int userId)
142+
{
143+
return QueryAstParser.Parse("""
144+
WITH user_permissions AS (
145+
SELECT rrp.region
146+
FROM region_reference_permission rrp
147+
WHERE rrp.user_id = :user_id
148+
)
149+
SELECT up.region FROM user_permissions up
150+
""")
151+
.AddParameter(":user_id", userId);
152+
}
153+
```
154+
155+
#### 🔍 Apply the Function in a Query
156+
157+
```csharp
158+
var query = QueryAstParser.Parse("...");
159+
query.Where("region", w => w.Exists(BuildRegionScalarQueryByUser(1)));
160+
```
161+
162+
By dynamically injecting permission-based filtering, we can ensure **secure and flexible query customization**.
163+
164+
## 📌 Conclusion
165+
166+
CarbunqleX makes raw SQL **more maintainable, reusable, and dynamically modifiable** without sacrificing performance. Its AST-based transformations provide a powerful way to manipulate queries at scale, making it an essential tool for advanced SQL users.

0 commit comments

Comments
 (0)