dzql 0.5.33 → 0.6.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/.env.sample +28 -0
- package/compose.yml +28 -0
- package/dist/client/index.ts +1 -0
- package/dist/client/stores/useMyProfileStore.ts +114 -0
- package/dist/client/stores/useOrgDashboardStore.ts +131 -0
- package/dist/client/stores/useVenueDetailStore.ts +117 -0
- package/dist/client/ws.ts +716 -0
- package/dist/db/migrations/000_core.sql +92 -0
- package/dist/db/migrations/20251229T212912022Z_schema.sql +3020 -0
- package/dist/db/migrations/20251229T212912022Z_subscribables.sql +371 -0
- package/dist/runtime/manifest.json +1562 -0
- package/docs/README.md +293 -36
- package/docs/feature-requests/applyPatch-bug-report.md +85 -0
- package/docs/feature-requests/connection-ready-profile.md +57 -0
- package/docs/feature-requests/hidden-bug-report.md +111 -0
- package/docs/feature-requests/hidden-fields-subscribables.md +34 -0
- package/docs/feature-requests/subscribable-param-key-bug.md +38 -0
- package/docs/feature-requests/todo.md +146 -0
- package/docs/for_ai.md +641 -0
- package/docs/project-setup.md +432 -0
- package/examples/blog.ts +50 -0
- package/examples/invalid.ts +18 -0
- package/examples/venues.js +485 -0
- package/package.json +23 -60
- package/src/cli/codegen/client.ts +99 -0
- package/src/cli/codegen/manifest.ts +95 -0
- package/src/cli/codegen/pinia.ts +174 -0
- package/src/cli/codegen/realtime.ts +58 -0
- package/src/cli/codegen/sql.ts +698 -0
- package/src/cli/codegen/subscribable_sql.ts +547 -0
- package/src/cli/codegen/subscribable_store.ts +184 -0
- package/src/cli/codegen/types.ts +142 -0
- package/src/cli/compiler/analyzer.ts +52 -0
- package/src/cli/compiler/graph_rules.ts +251 -0
- package/src/cli/compiler/ir.ts +233 -0
- package/src/cli/compiler/loader.ts +132 -0
- package/src/cli/compiler/permissions.ts +227 -0
- package/src/cli/index.ts +164 -0
- package/src/client/index.ts +1 -0
- package/src/client/ws.ts +286 -0
- package/src/create/.env.example +8 -0
- package/src/create/README.md +101 -0
- package/src/create/compose.yml +14 -0
- package/src/create/domain.ts +153 -0
- package/src/create/package.json +24 -0
- package/src/create/server.ts +18 -0
- package/src/create/setup.sh +11 -0
- package/src/create/tsconfig.json +15 -0
- package/src/runtime/auth.ts +39 -0
- package/src/runtime/db.ts +33 -0
- package/src/runtime/errors.ts +51 -0
- package/src/runtime/index.ts +98 -0
- package/src/runtime/js_functions.ts +63 -0
- package/src/runtime/manifest_loader.ts +29 -0
- package/src/runtime/namespace.ts +483 -0
- package/src/runtime/server.ts +87 -0
- package/src/runtime/ws.ts +197 -0
- package/src/shared/ir.ts +197 -0
- package/tests/client.test.ts +38 -0
- package/tests/codegen.test.ts +71 -0
- package/tests/compiler.test.ts +45 -0
- package/tests/graph_rules.test.ts +173 -0
- package/tests/integration/db.test.ts +174 -0
- package/tests/integration/e2e.test.ts +65 -0
- package/tests/integration/features.test.ts +922 -0
- package/tests/integration/full_stack.test.ts +262 -0
- package/tests/integration/setup.ts +45 -0
- package/tests/ir.test.ts +32 -0
- package/tests/namespace.test.ts +395 -0
- package/tests/permissions.test.ts +55 -0
- package/tests/pinia.test.ts +48 -0
- package/tests/realtime.test.ts +22 -0
- package/tests/runtime.test.ts +80 -0
- package/tests/subscribable_gen.test.ts +72 -0
- package/tests/subscribable_reactivity.test.ts +258 -0
- package/tests/venues_gen.test.ts +25 -0
- package/tsconfig.json +20 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/README.md +0 -90
- package/bin/cli.js +0 -727
- package/docs/compiler/ADVANCED_FILTERS.md +0 -183
- package/docs/compiler/CODING_STANDARDS.md +0 -415
- package/docs/compiler/COMPARISON.md +0 -673
- package/docs/compiler/QUICKSTART.md +0 -326
- package/docs/compiler/README.md +0 -134
- package/docs/examples/README.md +0 -38
- package/docs/examples/blog.sql +0 -160
- package/docs/examples/venue-detail-simple.sql +0 -8
- package/docs/examples/venue-detail-subscribable.sql +0 -45
- package/docs/for-ai/claude-guide.md +0 -1210
- package/docs/getting-started/quickstart.md +0 -125
- package/docs/getting-started/subscriptions-quick-start.md +0 -203
- package/docs/getting-started/tutorial.md +0 -1104
- package/docs/guides/atomic-updates.md +0 -299
- package/docs/guides/client-stores.md +0 -730
- package/docs/guides/composite-primary-keys.md +0 -158
- package/docs/guides/custom-functions.md +0 -362
- package/docs/guides/drop-semantics.md +0 -554
- package/docs/guides/field-defaults.md +0 -240
- package/docs/guides/interpreter-vs-compiler.md +0 -237
- package/docs/guides/many-to-many.md +0 -929
- package/docs/guides/subscriptions.md +0 -537
- package/docs/reference/api.md +0 -1373
- package/docs/reference/client.md +0 -224
- package/src/client/stores/index.js +0 -8
- package/src/client/stores/useAppStore.js +0 -285
- package/src/client/stores/useWsStore.js +0 -289
- package/src/client/ws.js +0 -762
- package/src/compiler/cli/compile-example.js +0 -33
- package/src/compiler/cli/compile-subscribable.js +0 -43
- package/src/compiler/cli/debug-compile.js +0 -44
- package/src/compiler/cli/debug-parse.js +0 -26
- package/src/compiler/cli/debug-path-parser.js +0 -18
- package/src/compiler/cli/debug-subscribable-parser.js +0 -21
- package/src/compiler/cli/index.js +0 -174
- package/src/compiler/codegen/auth-codegen.js +0 -153
- package/src/compiler/codegen/drop-semantics-codegen.js +0 -553
- package/src/compiler/codegen/graph-rules-codegen.js +0 -450
- package/src/compiler/codegen/notification-codegen.js +0 -232
- package/src/compiler/codegen/operation-codegen.js +0 -1382
- package/src/compiler/codegen/permission-codegen.js +0 -318
- package/src/compiler/codegen/subscribable-codegen.js +0 -827
- package/src/compiler/compiler.js +0 -371
- package/src/compiler/index.js +0 -11
- package/src/compiler/parser/entity-parser.js +0 -440
- package/src/compiler/parser/path-parser.js +0 -290
- package/src/compiler/parser/subscribable-parser.js +0 -244
- package/src/database/dzql-core.sql +0 -161
- package/src/database/migrations/001_schema.sql +0 -60
- package/src/database/migrations/002_functions.sql +0 -890
- package/src/database/migrations/003_operations.sql +0 -1135
- package/src/database/migrations/004_search.sql +0 -581
- package/src/database/migrations/005_entities.sql +0 -730
- package/src/database/migrations/006_auth.sql +0 -94
- package/src/database/migrations/007_events.sql +0 -133
- package/src/database/migrations/008_hello.sql +0 -18
- package/src/database/migrations/008a_meta.sql +0 -172
- package/src/database/migrations/009_subscriptions.sql +0 -240
- package/src/database/migrations/010_atomic_updates.sql +0 -157
- package/src/database/migrations/010_fix_m2m_events.sql +0 -94
- package/src/index.js +0 -40
- package/src/server/api.js +0 -9
- package/src/server/db.js +0 -442
- package/src/server/index.js +0 -317
- package/src/server/logger.js +0 -259
- package/src/server/mcp.js +0 -594
- package/src/server/meta-route.js +0 -251
- package/src/server/namespace.js +0 -292
- package/src/server/subscriptions.js +0 -351
- package/src/server/ws.js +0 -573
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
# Field Defaults
|
|
2
|
-
|
|
3
|
-
Auto-populate fields with default values during entity creation.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
Field defaults allow you to automatically set field values when creating new records, eliminating the need for clients to manually send fields like `owner_id`, `created_at`, or `status` on every save operation.
|
|
8
|
-
|
|
9
|
-
## Benefits
|
|
10
|
-
|
|
11
|
-
- **Less Client Code** - No need to send the same fields repeatedly
|
|
12
|
-
- **Prevents Errors** - Can't forget required fields
|
|
13
|
-
- **Enforces Security** - Server controls defaults (e.g., current user as owner)
|
|
14
|
-
- **Cleaner API** - Focus on actual data, not boilerplate
|
|
15
|
-
|
|
16
|
-
## Configuration
|
|
17
|
-
|
|
18
|
-
Field defaults are configured in the 10th parameter of `dzql.register_entity()`:
|
|
19
|
-
|
|
20
|
-
```sql
|
|
21
|
-
SELECT dzql.register_entity(
|
|
22
|
-
'resources',
|
|
23
|
-
'title',
|
|
24
|
-
ARRAY['title'],
|
|
25
|
-
'{}', -- fk_includes
|
|
26
|
-
false, -- soft_delete
|
|
27
|
-
'{}', -- temporal_fields
|
|
28
|
-
'{}', -- notification_paths
|
|
29
|
-
'{}', -- permission_paths
|
|
30
|
-
'{}', -- graph_rules
|
|
31
|
-
'{
|
|
32
|
-
"owner_id": "@user_id",
|
|
33
|
-
"created_by": "@user_id",
|
|
34
|
-
"created_at": "@now",
|
|
35
|
-
"status": "draft"
|
|
36
|
-
}' -- field_defaults (10th parameter)
|
|
37
|
-
);
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Available Variables
|
|
41
|
-
|
|
42
|
-
Field defaults support special variables that are resolved at runtime:
|
|
43
|
-
|
|
44
|
-
| Variable | Value | Example Use Case |
|
|
45
|
-
|----------|-------|------------------|
|
|
46
|
-
| `@user_id` | Current user ID from `p_user_id` | Ownership, audit trails |
|
|
47
|
-
| `@now` | Current timestamp | `created_at`, `updated_at` |
|
|
48
|
-
| `@today` | Current date | `valid_from`, `date_created` |
|
|
49
|
-
| Literal values | Any JSON value | `"draft"`, `0`, `true` |
|
|
50
|
-
|
|
51
|
-
## Behavior
|
|
52
|
-
|
|
53
|
-
### INSERT Operations
|
|
54
|
-
|
|
55
|
-
Field defaults are **only applied during INSERT** (creating new records):
|
|
56
|
-
|
|
57
|
-
```javascript
|
|
58
|
-
// Client doesn't send owner_id
|
|
59
|
-
await api.save_resources({
|
|
60
|
-
data: { title: "Conference Room A" }
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
// Server auto-populates:
|
|
64
|
-
// - owner_id = current user ID
|
|
65
|
-
// - created_at = current timestamp
|
|
66
|
-
// - status = "draft"
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### UPDATE Operations
|
|
70
|
-
|
|
71
|
-
Field defaults are **NOT applied during UPDATE** (modifying existing records):
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
// Updating existing record
|
|
75
|
-
await api.save_resources({
|
|
76
|
-
data: {
|
|
77
|
-
id: 1,
|
|
78
|
-
title: "Updated Title"
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
// created_at is NOT changed
|
|
83
|
-
// owner_id is NOT changed
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Explicit Values Override Defaults
|
|
87
|
-
|
|
88
|
-
If the client explicitly provides a value, it takes precedence:
|
|
89
|
-
|
|
90
|
-
```javascript
|
|
91
|
-
await api.save_resources({
|
|
92
|
-
data: {
|
|
93
|
-
title: "Room A",
|
|
94
|
-
status: "published" // Overrides "draft" default
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## Common Use Cases
|
|
100
|
-
|
|
101
|
-
### Ownership Tracking
|
|
102
|
-
|
|
103
|
-
```sql
|
|
104
|
-
SELECT dzql.register_entity(
|
|
105
|
-
'documents',
|
|
106
|
-
'title',
|
|
107
|
-
ARRAY['title'],
|
|
108
|
-
'{}', false, '{}', '{}', '{}', '{}',
|
|
109
|
-
'{
|
|
110
|
-
"owner_id": "@user_id",
|
|
111
|
-
"created_by": "@user_id"
|
|
112
|
-
}'
|
|
113
|
-
);
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Timestamps
|
|
117
|
-
|
|
118
|
-
```sql
|
|
119
|
-
SELECT dzql.register_entity(
|
|
120
|
-
'posts',
|
|
121
|
-
'title',
|
|
122
|
-
ARRAY['title'],
|
|
123
|
-
'{}', false, '{}', '{}', '{}', '{}',
|
|
124
|
-
'{
|
|
125
|
-
"created_at": "@now",
|
|
126
|
-
"published_at": "@now"
|
|
127
|
-
}'
|
|
128
|
-
);
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Status/Workflow
|
|
132
|
-
|
|
133
|
-
```sql
|
|
134
|
-
SELECT dzql.register_entity(
|
|
135
|
-
'orders',
|
|
136
|
-
'order_number',
|
|
137
|
-
ARRAY['order_number'],
|
|
138
|
-
'{}', false, '{}', '{}', '{}', '{}',
|
|
139
|
-
'{
|
|
140
|
-
"status": "pending",
|
|
141
|
-
"priority": "normal",
|
|
142
|
-
"auto_process": "true"
|
|
143
|
-
}'
|
|
144
|
-
);
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Multi-Tenant
|
|
148
|
-
|
|
149
|
-
```sql
|
|
150
|
-
SELECT dzql.register_entity(
|
|
151
|
-
'items',
|
|
152
|
-
'name',
|
|
153
|
-
ARRAY['name'],
|
|
154
|
-
'{}', false, '{}', '{}', '{}', '{}',
|
|
155
|
-
'{
|
|
156
|
-
"tenant_id": "@user_id",
|
|
157
|
-
"created_at": "@now",
|
|
158
|
-
"is_active": "true"
|
|
159
|
-
}'
|
|
160
|
-
);
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## Security Considerations
|
|
164
|
-
|
|
165
|
-
Field defaults improve security by:
|
|
166
|
-
|
|
167
|
-
1. **Preventing client-side tampering** - Server controls sensitive defaults
|
|
168
|
-
2. **Enforcing ownership** - Can't set wrong `owner_id`
|
|
169
|
-
3. **Audit trail integrity** - Timestamps set server-side
|
|
170
|
-
4. **Consistent initialization** - Every record starts in known state
|
|
171
|
-
|
|
172
|
-
## Example: Before vs After
|
|
173
|
-
|
|
174
|
-
### Before (Manual)
|
|
175
|
-
|
|
176
|
-
```javascript
|
|
177
|
-
// Client must remember to send owner_id every time
|
|
178
|
-
await api.save_tags({
|
|
179
|
-
data: {
|
|
180
|
-
name: "Important",
|
|
181
|
-
owner_id: user.id, // ← Easy to forget
|
|
182
|
-
created_at: new Date(), // ← Manual
|
|
183
|
-
status: "active" // ← Repetitive
|
|
184
|
-
}
|
|
185
|
-
})
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### After (Automatic)
|
|
189
|
-
|
|
190
|
-
```javascript
|
|
191
|
-
// Client sends only actual data
|
|
192
|
-
await api.save_tags({
|
|
193
|
-
data: {
|
|
194
|
-
name: "Important"
|
|
195
|
-
// owner_id, created_at, status auto-populated!
|
|
196
|
-
}
|
|
197
|
-
})
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## Backwards Compatibility
|
|
201
|
-
|
|
202
|
-
Field defaults are **completely optional**:
|
|
203
|
-
|
|
204
|
-
- Entities without field defaults work exactly as before
|
|
205
|
-
- No migration needed for existing entities
|
|
206
|
-
- Can be added incrementally
|
|
207
|
-
|
|
208
|
-
## Implementation Details
|
|
209
|
-
|
|
210
|
-
### Storage
|
|
211
|
-
|
|
212
|
-
Field defaults are stored in the `dzql.entities` table:
|
|
213
|
-
|
|
214
|
-
```sql
|
|
215
|
-
SELECT field_defaults FROM dzql.entities WHERE table_name = 'resources';
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
Result:
|
|
219
|
-
```json
|
|
220
|
-
{
|
|
221
|
-
"owner_id": "@user_id",
|
|
222
|
-
"created_at": "@now",
|
|
223
|
-
"status": "draft"
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Resolution
|
|
228
|
-
|
|
229
|
-
Variables are resolved in `generic_save()` using the existing `dzql.resolve_graph_variable()` function:
|
|
230
|
-
|
|
231
|
-
1. Check if field is missing in `p_data`
|
|
232
|
-
2. Get default value from entity config
|
|
233
|
-
3. If starts with `@`, resolve the variable
|
|
234
|
-
4. Add to data being inserted
|
|
235
|
-
|
|
236
|
-
## See Also
|
|
237
|
-
|
|
238
|
-
- [Entity Registration](../reference/api.md#register_entity) - Full registration API
|
|
239
|
-
- [Many-to-Many Support](./many-to-many.md) - Relationship defaults
|
|
240
|
-
- [Custom Functions](./custom-functions.md) - Extending entities
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
# Interpreter vs Compiler Mode
|
|
2
|
-
|
|
3
|
-
DZQL offers two execution modes for your entities. Understanding when to use each is fundamental to getting the best out of the framework.
|
|
4
|
-
|
|
5
|
-
## Quick Summary
|
|
6
|
-
|
|
7
|
-
| Aspect | Interpreter | Compiler |
|
|
8
|
-
|--------|-------------|----------|
|
|
9
|
-
| **Setup** | Register entity, use immediately | Register entity, compile, deploy SQL |
|
|
10
|
-
| **Performance** | ~8-12ms per operation | ~2-4ms per operation |
|
|
11
|
-
| **Debugging** | Opaque (dynamic SQL) | Transparent (static SQL) |
|
|
12
|
-
| **Best For** | Development, prototyping | Production, performance-critical |
|
|
13
|
-
|
|
14
|
-
## How It Works
|
|
15
|
-
|
|
16
|
-
### Interpreter Mode (Runtime)
|
|
17
|
-
|
|
18
|
-
Entity configuration is stored as JSON in `dzql.entities` table and parsed at runtime:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
Client Request → generic_exec() → Parse JSON config → Build SQL → Execute
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
**Characteristics:**
|
|
25
|
-
- Zero build step - changes take effect immediately
|
|
26
|
-
- JSON config parsed on every request
|
|
27
|
-
- Dynamic SQL generated at runtime
|
|
28
|
-
- Generic query plans (harder to optimize)
|
|
29
|
-
|
|
30
|
-
**Usage:**
|
|
31
|
-
```sql
|
|
32
|
-
-- Register entity
|
|
33
|
-
SELECT dzql.register_entity('todos', 'title', ARRAY['title'], ...);
|
|
34
|
-
|
|
35
|
-
-- Use immediately via generic executor
|
|
36
|
-
SELECT dzql.generic_exec('save', 'todos', '{"title": "Buy milk"}'::jsonb, 1);
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Compiler Mode (Static)
|
|
40
|
-
|
|
41
|
-
Entity configuration is compiled into dedicated PostgreSQL functions:
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
Entity Definition → dzql compile → Static SQL Functions → Deploy → Execute
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**Characteristics:**
|
|
48
|
-
- Build step required
|
|
49
|
-
- No JSON parsing at runtime
|
|
50
|
-
- Static SQL with specific query plans
|
|
51
|
-
- PostgreSQL can optimize and cache plans
|
|
52
|
-
|
|
53
|
-
**Usage:**
|
|
54
|
-
```bash
|
|
55
|
-
# Compile entities to SQL
|
|
56
|
-
dzql compile entities.sql -o compiled/
|
|
57
|
-
|
|
58
|
-
# Deploy to database
|
|
59
|
-
psql < compiled/entities.sql
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
```sql
|
|
63
|
-
-- Use compiled functions directly
|
|
64
|
-
SELECT save_todos('{"title": "Buy milk"}'::jsonb, 1);
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## The Server Automatically Chooses
|
|
68
|
-
|
|
69
|
-
The DZQL server (`db.js`) automatically tries compiled functions first:
|
|
70
|
-
|
|
71
|
-
```javascript
|
|
72
|
-
// In callDZQLOperation()
|
|
73
|
-
try {
|
|
74
|
-
// Try compiled function: save_todos()
|
|
75
|
-
const result = await sql.unsafe(`SELECT save_todos($1, $2)`, [data, userId]);
|
|
76
|
-
return result[0].result;
|
|
77
|
-
} catch (error) {
|
|
78
|
-
// If compiled function doesn't exist, fall back to interpreter
|
|
79
|
-
if (error.message.includes('save_todos') && error.code === '42883') {
|
|
80
|
-
return await sql`SELECT dzql.generic_exec('save', 'todos', ${data}, ${userId})`;
|
|
81
|
-
}
|
|
82
|
-
throw error;
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
This means you can:
|
|
87
|
-
1. Start with interpreter mode during development
|
|
88
|
-
2. Compile and deploy when ready for production
|
|
89
|
-
3. Mix and match - some entities compiled, others interpreted
|
|
90
|
-
|
|
91
|
-
## Performance Comparison
|
|
92
|
-
|
|
93
|
-
### Interpreter (Runtime Parsing)
|
|
94
|
-
|
|
95
|
-
```sql
|
|
96
|
-
SELECT dzql.generic_exec('save', 'venues', '{"name": "MSG"}'::jsonb, 42);
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
**Execution steps:**
|
|
100
|
-
1. Fetch entity config from `dzql.entities` (table lookup)
|
|
101
|
-
2. Parse `permission_paths` JSONB
|
|
102
|
-
3. Build permission query dynamically
|
|
103
|
-
4. Parse `graph_rules` JSONB
|
|
104
|
-
5. Execute rules via dynamic SQL
|
|
105
|
-
6. Parse `notification_paths` JSONB
|
|
106
|
-
7. Resolve paths dynamically
|
|
107
|
-
8. Execute the actual save
|
|
108
|
-
|
|
109
|
-
**Cost:** ~8-12ms, 3-5 JSONB parses, unpredictable query plans
|
|
110
|
-
|
|
111
|
-
### Compiler (Pre-built Functions)
|
|
112
|
-
|
|
113
|
-
```sql
|
|
114
|
-
SELECT save_venues('{"name": "MSG"}'::jsonb, 42);
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
**Execution steps:**
|
|
118
|
-
1. Call `can_update_venues()` - pre-compiled permission check
|
|
119
|
-
2. Execute INSERT/UPDATE - direct SQL
|
|
120
|
-
3. Call `graph_venues_on_create()` - pre-compiled graph rules
|
|
121
|
-
4. Call `resolve_notification_paths_venues()` - pre-compiled
|
|
122
|
-
5. Done
|
|
123
|
-
|
|
124
|
-
**Cost:** ~2-4ms, 0 JSONB parses, optimized query plans
|
|
125
|
-
|
|
126
|
-
## When to Use Each
|
|
127
|
-
|
|
128
|
-
### Use Interpreter When:
|
|
129
|
-
- Rapid prototyping and development
|
|
130
|
-
- Schema changes frequently
|
|
131
|
-
- Learning DZQL concepts
|
|
132
|
-
- Small applications with low traffic
|
|
133
|
-
- Need maximum flexibility
|
|
134
|
-
|
|
135
|
-
### Use Compiler When:
|
|
136
|
-
- Production deployments
|
|
137
|
-
- Performance is critical
|
|
138
|
-
- Need predictable query performance
|
|
139
|
-
- Want reviewable/auditable SQL
|
|
140
|
-
- Large teams (generated SQL is easy to review)
|
|
141
|
-
- Complex permission or graph rules
|
|
142
|
-
|
|
143
|
-
### Recommended Workflow:
|
|
144
|
-
1. **Development:** Use interpreter for fast iteration
|
|
145
|
-
2. **Staging:** Compile and test performance
|
|
146
|
-
3. **Production:** Deploy compiled functions
|
|
147
|
-
|
|
148
|
-
## Compiling Entities
|
|
149
|
-
|
|
150
|
-
### Via CLI
|
|
151
|
-
|
|
152
|
-
```bash
|
|
153
|
-
# Single file
|
|
154
|
-
dzql compile database/entities.sql -o compiled/
|
|
155
|
-
|
|
156
|
-
# Multiple files
|
|
157
|
-
dzql compile database/*.sql -o compiled/
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Programmatically
|
|
161
|
-
|
|
162
|
-
```javascript
|
|
163
|
-
import { DZQLCompiler } from 'dzql/compiler';
|
|
164
|
-
|
|
165
|
-
const compiler = new DZQLCompiler();
|
|
166
|
-
const result = compiler.compileFromSQL(sqlContent);
|
|
167
|
-
|
|
168
|
-
console.log(result.sql); // Generated PostgreSQL functions
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### What Gets Generated
|
|
172
|
-
|
|
173
|
-
For each entity, the compiler generates:
|
|
174
|
-
|
|
175
|
-
| Function | Purpose |
|
|
176
|
-
|----------|---------|
|
|
177
|
-
| `get_{entity}(id, user_id)` | Retrieve single record |
|
|
178
|
-
| `save_{entity}(data, user_id)` | Create or update |
|
|
179
|
-
| `delete_{entity}(id, user_id)` | Delete record |
|
|
180
|
-
| `lookup_{entity}(term, user_id)` | Autocomplete search |
|
|
181
|
-
| `search_{entity}(filters, user_id)` | Paginated search |
|
|
182
|
-
| `can_view_{entity}(user_id, record)` | Permission check |
|
|
183
|
-
| `can_create_{entity}(user_id, record)` | Permission check |
|
|
184
|
-
| `can_update_{entity}(user_id, record)` | Permission check |
|
|
185
|
-
| `can_delete_{entity}(user_id, record)` | Permission check |
|
|
186
|
-
|
|
187
|
-
## Debugging
|
|
188
|
-
|
|
189
|
-
### Interpreter Mode
|
|
190
|
-
|
|
191
|
-
Debugging is harder because SQL is generated dynamically:
|
|
192
|
-
|
|
193
|
-
```sql
|
|
194
|
-
-- You see this
|
|
195
|
-
EXPLAIN ANALYZE SELECT dzql.generic_exec('save', 'venues', '...');
|
|
196
|
-
|
|
197
|
-
-- But the actual query is hidden inside
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### Compiler Mode
|
|
201
|
-
|
|
202
|
-
Standard PostgreSQL tools work:
|
|
203
|
-
|
|
204
|
-
```sql
|
|
205
|
-
-- See the actual function
|
|
206
|
-
\sf save_venues
|
|
207
|
-
|
|
208
|
-
-- Analyze performance
|
|
209
|
-
EXPLAIN ANALYZE SELECT save_venues('{"name": "MSG"}'::jsonb, 42);
|
|
210
|
-
|
|
211
|
-
-- Check slow queries
|
|
212
|
-
SELECT * FROM pg_stat_statements WHERE query LIKE '%save_venues%';
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## Feature Parity
|
|
216
|
-
|
|
217
|
-
Both modes support the same features:
|
|
218
|
-
|
|
219
|
-
| Feature | Interpreter | Compiler |
|
|
220
|
-
|---------|-------------|----------|
|
|
221
|
-
| CRUD operations | ✅ | ✅ |
|
|
222
|
-
| Permission paths | ✅ | ✅ |
|
|
223
|
-
| Graph rules | ✅ | ✅ |
|
|
224
|
-
| Notification paths | ✅ | ✅ |
|
|
225
|
-
| FK includes | ✅ | ✅ |
|
|
226
|
-
| Many-to-many | ✅ | ✅ |
|
|
227
|
-
| Field defaults | ✅ | ✅ |
|
|
228
|
-
| Soft delete | ✅ | ✅ |
|
|
229
|
-
| Temporal fields | ✅ | ✅ |
|
|
230
|
-
|
|
231
|
-
The difference is purely in execution speed and debuggability, not functionality.
|
|
232
|
-
|
|
233
|
-
## See Also
|
|
234
|
-
|
|
235
|
-
- [Compiler Quickstart](../compiler/QUICKSTART.md) - Get started with compilation
|
|
236
|
-
- [Compiler Comparison](../compiler/COMPARISON.md) - Detailed side-by-side analysis
|
|
237
|
-
- [API Reference](../reference/api.md) - The 5 operations
|