sql_fusion 1.2.0__tar.gz → 1.2.1__tar.gz
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.
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/PKG-INFO +91 -2
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/README.md +89 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/pyproject.toml +2 -2
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/composite_table.py +2 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/__init__.py +0 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/operators.py +0 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/query/__init__.py +0 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/query/delete.py +0 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/query/insert.py +0 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/query/select.py +0 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/query/sets.py +0 -0
- {sql_fusion-1.2.0 → sql_fusion-1.2.1}/src/sql_fusion/query/update.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sql_fusion
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Python query builder with a focus on composability and reusability.
|
|
5
5
|
Author: Mastermind-U
|
|
6
6
|
Author-email: Mastermind-U <rex49513@gmail.com>
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
8
|
Project-URL: Homepage, https://github.com/Mastermind-U/sql_fusion
|
|
9
9
|
Project-URL: Documentation, https://github.com/Mastermind-U/sql_fusion/blob/main/README.md
|
|
10
10
|
Project-URL: Repository, https://github.com/Mastermind-U/sql_fusion.git
|
|
@@ -40,6 +40,7 @@ That makes it easy to plug into your own connection layer.
|
|
|
40
40
|
- [Quickstart: psycopg3](#quickstart-psycopg3)
|
|
41
41
|
- [Query Basics](#query-basics)
|
|
42
42
|
- [Subquery Example](#subquery-example)
|
|
43
|
+
- [Set Operations](#set-operations)
|
|
43
44
|
- [Method Reference](#method-reference)
|
|
44
45
|
- [Functions](#functions)
|
|
45
46
|
- [CTEs](#ctes)
|
|
@@ -404,6 +405,94 @@ paid_orders = (
|
|
|
404
405
|
query, params = select().from_(paid_orders).compile()
|
|
405
406
|
```
|
|
406
407
|
|
|
408
|
+
## Set Operations
|
|
409
|
+
|
|
410
|
+
SQL Fusion supports compound queries through three small wrapper classes:
|
|
411
|
+
|
|
412
|
+
- `union(query1, query2, all=False, by_name=False)`
|
|
413
|
+
- `intersect(q1, q2, all_=False)`
|
|
414
|
+
- `except_(q1, q2, all_=False)`
|
|
415
|
+
|
|
416
|
+
Each builder accepts two query objects and returns a new query that compiles to
|
|
417
|
+
the matching SQL set operation.
|
|
418
|
+
|
|
419
|
+
### `union(...)`
|
|
420
|
+
|
|
421
|
+
```python
|
|
422
|
+
users = Table("users")
|
|
423
|
+
archived_users = Table("archived_users")
|
|
424
|
+
|
|
425
|
+
active_users = select(users.id, users.name).from_(users).where_by(status="active")
|
|
426
|
+
archived_active_users = (
|
|
427
|
+
select(archived_users.id, archived_users.name)
|
|
428
|
+
.from_(archived_users)
|
|
429
|
+
.where_by(status="active")
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
query, params = union(active_users, archived_active_users).compile()
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Use `all=True` for `UNION ALL`:
|
|
436
|
+
|
|
437
|
+
```python
|
|
438
|
+
query, params = union(active_users, archived_active_users, all=True).compile()
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Use `by_name=True` when the two result sets expose the same logical columns in
|
|
442
|
+
different orders:
|
|
443
|
+
|
|
444
|
+
```python
|
|
445
|
+
left = select(users.id, users.name).from_(users)
|
|
446
|
+
right = select(archived_users.name, archived_users.id).from_(archived_users)
|
|
447
|
+
|
|
448
|
+
query, params = union(left, right, all=True, by_name=True).compile()
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### `intersect(...)`
|
|
452
|
+
|
|
453
|
+
```python
|
|
454
|
+
users = Table("users")
|
|
455
|
+
premium_users = Table("premium_users")
|
|
456
|
+
|
|
457
|
+
active_users = select(users.id).from_(users).where_by(status="active")
|
|
458
|
+
premium_active_users = (
|
|
459
|
+
select(premium_users.id).from_(premium_users).where_by(status="active")
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
query, params = intersect(active_users, premium_active_users).compile()
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Use `all_=True` for `INTERSECT ALL`:
|
|
466
|
+
|
|
467
|
+
```python
|
|
468
|
+
query, params = intersect(
|
|
469
|
+
active_users,
|
|
470
|
+
premium_active_users,
|
|
471
|
+
all_=True,
|
|
472
|
+
).compile()
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### `except_(...)`
|
|
476
|
+
|
|
477
|
+
```python
|
|
478
|
+
users = Table("users")
|
|
479
|
+
banned_users = Table("banned_users")
|
|
480
|
+
|
|
481
|
+
all_users = select(users.id).from_(users)
|
|
482
|
+
banned_user_ids = select(banned_users.id).from_(banned_users)
|
|
483
|
+
|
|
484
|
+
query, params = except_(all_users, banned_user_ids).compile()
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
Use `all_=True` for `EXCEPT ALL`:
|
|
488
|
+
|
|
489
|
+
```python
|
|
490
|
+
query, params = except_(all_users, banned_user_ids, all_=True).compile()
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
These builders preserve the parameter order from left to right, so the returned
|
|
494
|
+
`params` tuple can be passed directly to DB-API drivers.
|
|
495
|
+
|
|
407
496
|
### Having Example
|
|
408
497
|
|
|
409
498
|
```python
|
|
@@ -26,6 +26,7 @@ That makes it easy to plug into your own connection layer.
|
|
|
26
26
|
- [Quickstart: psycopg3](#quickstart-psycopg3)
|
|
27
27
|
- [Query Basics](#query-basics)
|
|
28
28
|
- [Subquery Example](#subquery-example)
|
|
29
|
+
- [Set Operations](#set-operations)
|
|
29
30
|
- [Method Reference](#method-reference)
|
|
30
31
|
- [Functions](#functions)
|
|
31
32
|
- [CTEs](#ctes)
|
|
@@ -390,6 +391,94 @@ paid_orders = (
|
|
|
390
391
|
query, params = select().from_(paid_orders).compile()
|
|
391
392
|
```
|
|
392
393
|
|
|
394
|
+
## Set Operations
|
|
395
|
+
|
|
396
|
+
SQL Fusion supports compound queries through three small wrapper classes:
|
|
397
|
+
|
|
398
|
+
- `union(query1, query2, all=False, by_name=False)`
|
|
399
|
+
- `intersect(q1, q2, all_=False)`
|
|
400
|
+
- `except_(q1, q2, all_=False)`
|
|
401
|
+
|
|
402
|
+
Each builder accepts two query objects and returns a new query that compiles to
|
|
403
|
+
the matching SQL set operation.
|
|
404
|
+
|
|
405
|
+
### `union(...)`
|
|
406
|
+
|
|
407
|
+
```python
|
|
408
|
+
users = Table("users")
|
|
409
|
+
archived_users = Table("archived_users")
|
|
410
|
+
|
|
411
|
+
active_users = select(users.id, users.name).from_(users).where_by(status="active")
|
|
412
|
+
archived_active_users = (
|
|
413
|
+
select(archived_users.id, archived_users.name)
|
|
414
|
+
.from_(archived_users)
|
|
415
|
+
.where_by(status="active")
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
query, params = union(active_users, archived_active_users).compile()
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Use `all=True` for `UNION ALL`:
|
|
422
|
+
|
|
423
|
+
```python
|
|
424
|
+
query, params = union(active_users, archived_active_users, all=True).compile()
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Use `by_name=True` when the two result sets expose the same logical columns in
|
|
428
|
+
different orders:
|
|
429
|
+
|
|
430
|
+
```python
|
|
431
|
+
left = select(users.id, users.name).from_(users)
|
|
432
|
+
right = select(archived_users.name, archived_users.id).from_(archived_users)
|
|
433
|
+
|
|
434
|
+
query, params = union(left, right, all=True, by_name=True).compile()
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### `intersect(...)`
|
|
438
|
+
|
|
439
|
+
```python
|
|
440
|
+
users = Table("users")
|
|
441
|
+
premium_users = Table("premium_users")
|
|
442
|
+
|
|
443
|
+
active_users = select(users.id).from_(users).where_by(status="active")
|
|
444
|
+
premium_active_users = (
|
|
445
|
+
select(premium_users.id).from_(premium_users).where_by(status="active")
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
query, params = intersect(active_users, premium_active_users).compile()
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
Use `all_=True` for `INTERSECT ALL`:
|
|
452
|
+
|
|
453
|
+
```python
|
|
454
|
+
query, params = intersect(
|
|
455
|
+
active_users,
|
|
456
|
+
premium_active_users,
|
|
457
|
+
all_=True,
|
|
458
|
+
).compile()
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### `except_(...)`
|
|
462
|
+
|
|
463
|
+
```python
|
|
464
|
+
users = Table("users")
|
|
465
|
+
banned_users = Table("banned_users")
|
|
466
|
+
|
|
467
|
+
all_users = select(users.id).from_(users)
|
|
468
|
+
banned_user_ids = select(banned_users.id).from_(banned_users)
|
|
469
|
+
|
|
470
|
+
query, params = except_(all_users, banned_user_ids).compile()
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Use `all_=True` for `EXCEPT ALL`:
|
|
474
|
+
|
|
475
|
+
```python
|
|
476
|
+
query, params = except_(all_users, banned_user_ids, all_=True).compile()
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
These builders preserve the parameter order from left to right, so the returned
|
|
480
|
+
`params` tuple can be passed directly to DB-API drivers.
|
|
481
|
+
|
|
393
482
|
### Having Example
|
|
394
483
|
|
|
395
484
|
```python
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sql_fusion"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.1"
|
|
4
4
|
description = "Python query builder with a focus on composability and reusability."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [{ name = "Mastermind-U", email = "rex49513@gmail.com" }]
|
|
7
|
-
requires-python = ">=3.
|
|
7
|
+
requires-python = ">=3.11"
|
|
8
8
|
dependencies = []
|
|
9
9
|
|
|
10
10
|
[project.urls]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|