Skip to content

Commit 1a406c7

Browse files
docs: Add multi-dimensional array support documentation
Updated documentation across README, CHANGELOG, and CLAUDE.md: - Added multi-dimensional arrays section to README with usage examples - Updated Supported Features table to include multi-dim arrays - Added comprehensive CHANGELOG entry for issue #49 - Enhanced CLAUDE.md with implementation details and type system info 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 06ca382 commit 1a406c7

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
## [Unreleased]
44

5+
### Added
6+
- **Multi-Dimensional Array Support** (fixes #49)
7+
- Added `Dimensions` field to `pg.FieldSchema` to store array dimensionality (1D, 2D, 3D, 4D+)
8+
- Implemented `detectArrayDimensions()` to automatically detect dimensions from PostgreSQL type strings
9+
* Supports bracket notation: `integer[]` (1D), `integer[][]` (2D), `integer[][][]` (3D)
10+
* Supports underscore notation: `_int4` (1D), `_int4[]` (2D), `_int4[][]` (3D)
11+
* Correctly combines both notations (e.g., `_int4[]` = 2D array)
12+
- Updated `LoadTableSchema()` to query `udt_name` column and detect dimensions automatically
13+
- Modified `getArrayDimension()` to use CEL typeMap for accurate type resolution
14+
- Enhanced ARRAY_LENGTH SQL generation to use detected dimensions: `ARRAY_LENGTH(field, N)`
15+
- Full backward compatibility: defaults to dimension 1 when no schema provided
16+
- Comprehensive test coverage: 22 unit tests + integration tests for 1D-4D arrays
17+
- Example: `size(matrix)` where `matrix integer[][]``COALESCE(ARRAY_LENGTH(matrix, 2), 0)`
18+
519
## [3.4.0] - 2025-10-31
620

721
### Added

CLAUDE.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,46 @@ The library uses CEL's protobuf-based type system (`exprpb.Type`, `exprpb.Expr`)
104104
**Structured Types:**
105105
- `json`, `jsonb``decls.Dyn` (with automatic JSON path support)
106106
- Arrays: Set `Repeated: true` in schema
107+
- Multi-dimensional arrays: Set `Repeated: true` and `Dimensions: N` in schema
107108
- Composite types: Use nested `Schema` fields
108109

109110
**Unsupported Types:**
110111
Unknown PostgreSQL types (e.g., `point`, `polygon`, `box`, custom enums) will cause `FindStructFieldType()` to return `found=false`. This prevents silent type mismatches. Add explicit support for custom types or use composite type definitions.
111112

113+
### Multi-Dimensional Array Support
114+
115+
cel2sql supports PostgreSQL multi-dimensional arrays (1D, 2D, 3D, 4D+) with automatic dimension detection.
116+
117+
**Dimension Detection:**
118+
- Automatically detects dimensions from PostgreSQL type strings via `detectArrayDimensions()`
119+
- Supports bracket notation: `integer[]` (1D), `integer[][]` (2D), `integer[][][]` (3D)
120+
- Supports underscore notation: `_int4` (1D), `_int4[]` (2D), `_int4[][]` (3D)
121+
- Correctly combines both notations (e.g., `_int4[]` = 2D: 1 from underscore + 1 from bracket)
122+
123+
**Schema Definition:**
124+
```go
125+
schema := pg.NewSchema([]pg.FieldSchema{
126+
{Name: "tags", Type: "text", Repeated: true, Dimensions: 1}, // 1D: text[]
127+
{Name: "matrix", Type: "integer", Repeated: true, Dimensions: 2}, // 2D: integer[][]
128+
{Name: "cube", Type: "float", Repeated: true, Dimensions: 3}, // 3D: float[][][]
129+
})
130+
```
131+
132+
**SQL Generation:**
133+
- `size()` function automatically uses correct dimension in `ARRAY_LENGTH(field, dimension)`
134+
- Example: `size(matrix)` where `matrix integer[][]``COALESCE(ARRAY_LENGTH(matrix, 2), 0)`
135+
- Dimension lookup uses CEL typeMap for accurate type resolution in `getArrayDimension()`
136+
137+
**Backward Compatibility:**
138+
- Arrays without schema information default to dimension 1
139+
- Explicit `Dimensions: 0` defaults to dimension 1
140+
- Existing code continues to work without changes
141+
142+
**Implementation Details:**
143+
- `pg/provider.go`: Contains `detectArrayDimensions()` and dimension detection logic
144+
- `cel2sql.go`: Contains `getArrayDimension()` that uses CEL typeMap for lookup
145+
- `LoadTableSchema()`: Queries `udt_name` column to detect dimensions from database
146+
112147
### JSON/JSONB Support
113148

114149
CEL field access on JSON/JSONB columns automatically converts to PostgreSQL JSON path operations:

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,32 @@ user.scores.all(s, s >= 60)
315315
// SQL: NOT EXISTS (SELECT 1 FROM UNNEST(user.scores) AS s WHERE NOT (s >= 60))
316316
```
317317

318+
### 6. Multi-Dimensional Arrays
319+
320+
cel2sql supports PostgreSQL multi-dimensional arrays (1D, 2D, 3D, 4D+) with automatic dimension detection:
321+
322+
```go
323+
// Define schema with multi-dimensional arrays
324+
schema := pg.NewSchema([]pg.FieldSchema{
325+
{Name: "tags", Type: "text", Repeated: true, Dimensions: 1}, // 1D: text[]
326+
{Name: "matrix", Type: "integer", Repeated: true, Dimensions: 2}, // 2D: integer[][]
327+
{Name: "cube", Type: "float", Repeated: true, Dimensions: 3}, // 3D: float[][][]
328+
})
329+
330+
// CEL: size() automatically uses correct dimension
331+
ast, _ := env.Compile("size(data.matrix) > 0")
332+
// SQL: COALESCE(ARRAY_LENGTH(data.matrix, 2), 0) > 0
333+
334+
// Or load dimensions automatically from database
335+
provider, _ := pg.NewTypeProviderWithConnection(ctx, connString)
336+
provider.LoadTableSchema(ctx, "products") // Dimensions detected from schema
337+
```
338+
339+
**Dimension Detection:**
340+
- Detects dimensions from PostgreSQL type strings (`integer[][]`, `_int4[]`)
341+
- Works with both bracket notation and underscore notation
342+
- Defaults to 1D for backward compatibility when no schema is provided
343+
318344
## Documentation
319345

320346
- 📖 **[Getting Started Guide](docs/getting-started.md)** - Step-by-step tutorial
@@ -333,6 +359,7 @@ user.scores.all(s, s >= 60)
333359
| Logic | `active && verified` | `active IS TRUE AND verified IS TRUE` |
334360
| Strings | `name.startsWith("A")` | `name LIKE 'A%'` |
335361
| Lists | `"admin" in roles` | `'admin' IN UNNEST(roles)` |
362+
| Multi-Dim Arrays | `size(matrix) > 0` | `COALESCE(ARRAY_LENGTH(matrix, 2), 0) > 0` |
336363
| JSON | `data.key == "value"` | `data->>'key' = 'value'` |
337364
| Regex | `email.matches(r".*@test\.com")` | `email ~ '.*@test\.com'` |
338365
| Dates | `created_at.getFullYear() == 2024` | `EXTRACT(YEAR FROM created_at) = 2024` |

0 commit comments

Comments
 (0)