Commit 12a4501
authored
Adding COUNT and COUNT(DISTINCT) aggregation support (#97)
## Summary
- Implements COUNT and COUNT(DISTINCT) aggregations for ScalaSQL
addressing issue -->
#95
- Adds comprehensive API with proper SQL semantics and NULL handling
- Provides full cross-dialect compatibility and extensive test coverage
- Includes complete documentation following existing patterns
## Changes Made
### Core Operations
- **`.countBy(_.column)`** - Generates `COUNT(column)` SQL, ignores NULL
values
- **`.countDistinctBy(_.column)`** - Generates `COUNT(DISTINCT column)`
SQL for unique non-NULL counts
- **`.count`** on mapped expressions - `query.map(_.expr).count`
- **`.countDistinct`** on mapped expressions -
`query.map(_.expr).countDistinct`
### Advanced Usage
```scala
// Basic counting
Purchase.select.countBy(_.productId) // COUNT(product_id)
Purchase.select.countDistinctBy(_.productId) // COUNT(DISTINCT
product_id)
// Expression counting
Purchase.select.map(_.total * 2).count // COUNT(total * 2)
Purchase.select.map(p => p.productId % 2).countDistinct //
COUNT(DISTINCT productId % 2)
// With filters and group by
Purchase.select.filter(_.total > 100).countBy(_.productId)
Purchase.select.groupBy(_.shippingInfoId)(agg =>
agg.countDistinctBy(_.productId))
// Multiple aggregates
Purchase.select.aggregate(agg => (
agg.countBy(_.productId),
agg.countDistinctBy(_.productId),
agg.sumBy(_.total)
))
```
### Files Added/Modified
- AggAnyOps.scala - New operations for Aggregatable[Expr[T]]
- AggOps.scala - Enhanced with countBy/countDistinctBy methods
- DbCountOpsTests.scala - Basic COUNT operation tests
- DbCountOpsOptionTests.scala - NULL handling and Option type tests
- DbCountOpsAdvancedTests.scala - Complex expressions and edge cases
### Database compatibility
- PostgreSQL - MOD() function
- MySQL - MOD() function
- SQLite - % operator
- H2 - MOD() function
- MS SQL Server - % operator
### Test Coverage
- **DbCountOpsTests.scala** (new): Basic COUNT operations, GROUP BY, filters, joins
- **DbCountOpsAdvancedTests.scala** (new): Complex types, edge cases, Option handling
- Cross-dialect testing for PostgreSQL, MySQL, SQLite, H2, MS SQL Server
- Window function and CTE integration tests
- NULL value handling with Option types
- Arithmetic expressions (addition, multiplication, modulo)
- String operations and concatenation
- Complex filtering and grouping scenarios
- Multi-dialect SQL generation
- Cross-database compatibility verification
### Documentation
- **tutorial.md**: Added COUNT examples after existing `.size` documentation
- **cheatsheet.md**: Updated aggregate functions table and quick reference
- **Window functions**: Added COUNT support documentation
## Test Plan
- [x] Compiles successfully for Scala 2.13.12 and 3.6.2
- [x] All existing tests continue to pass
- [x] Window functions integrate correctly with existing patterns
- [x] Documentation examples validated against actual API
- [x] New COUNT operations work across all supported database dialects
- [x] All newly created tests pass
- [x] Proper NULL handling verified with Option types
#951 parent 9a504dd commit 12a4501
File tree
9 files changed
+1266
-9
lines changed- docs
- scalasql
- operations/src
- src/dialects
- test/src
- operations
9 files changed
+1266
-9
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
70 | 82 | | |
71 | 83 | | |
72 | 84 | | |
| |||
200 | 212 | | |
201 | 213 | | |
202 | 214 | | |
203 | | - | |
204 | | - | |
205 | | - | |
206 | | - | |
207 | | - | |
208 | | - | |
209 | | - | |
210 | | - | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
211 | 225 | | |
212 | 226 | | |
213 | 227 | | |
| |||
0 commit comments