dzql 0.5.0 → 0.5.2
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/bin/cli.js
CHANGED
|
@@ -240,7 +240,7 @@ CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
240
240
|
|
|
241
241
|
-- Register new user
|
|
242
242
|
-- p_options: optional JSON object with additional fields to set on the user record
|
|
243
|
-
CREATE OR REPLACE FUNCTION register_user(p_email TEXT, p_password TEXT, p_options
|
|
243
|
+
CREATE OR REPLACE FUNCTION register_user(p_email TEXT, p_password TEXT, p_options JSON DEFAULT NULL)
|
|
244
244
|
RETURNS JSONB
|
|
245
245
|
LANGUAGE plpgsql
|
|
246
246
|
SECURITY DEFINER
|
|
@@ -256,9 +256,10 @@ BEGIN
|
|
|
256
256
|
v_hash := crypt(p_password, v_salt);
|
|
257
257
|
|
|
258
258
|
-- Build insert data: options fields + email + password_hash
|
|
259
|
+
-- Cast p_options to JSONB for internal operations (JSON type is for API boundary convenience)
|
|
259
260
|
v_insert_data := jsonb_build_object('email', p_email, 'password_hash', v_hash);
|
|
260
261
|
IF p_options IS NOT NULL THEN
|
|
261
|
-
v_insert_data := (p_options - 'id' - 'email' - 'password_hash' - 'password') || v_insert_data;
|
|
262
|
+
v_insert_data := (p_options::jsonb - 'id' - 'email' - 'password_hash' - 'password') || v_insert_data;
|
|
262
263
|
END IF;
|
|
263
264
|
|
|
264
265
|
-- Dynamic INSERT from JSONB
|
|
@@ -72,6 +72,72 @@ CREATE FUNCTION lookup_users(p_user_id INT, p_filter TEXT, ...)
|
|
|
72
72
|
CREATE FUNCTION search_users(p_user_id INT, p_filters JSONB, ...)
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
## JSON vs JSONB for Function Parameters
|
|
76
|
+
|
|
77
|
+
### External API Parameters: Use JSON
|
|
78
|
+
|
|
79
|
+
When defining function parameters that accept JSON from external callers (API boundary), use `JSON` type (text-based) rather than `JSONB`. This allows callers to pass `JSON.stringify(options)` as a plain string without needing special serialization like `sql.json()`.
|
|
80
|
+
|
|
81
|
+
```sql
|
|
82
|
+
-- ✅ CORRECT - JSON for external input parameters
|
|
83
|
+
CREATE FUNCTION register_user(
|
|
84
|
+
p_email TEXT,
|
|
85
|
+
p_password TEXT,
|
|
86
|
+
p_options JSON DEFAULT NULL -- Accepts plain JSON string from API
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
-- ❌ WRONG - JSONB requires special serialization from clients
|
|
90
|
+
CREATE FUNCTION register_user(
|
|
91
|
+
p_email TEXT,
|
|
92
|
+
p_password TEXT,
|
|
93
|
+
p_options JSONB DEFAULT NULL -- Harder to call from JavaScript
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Internal Operations: Cast to JSONB
|
|
98
|
+
|
|
99
|
+
Inside the function, cast to JSONB if you need JSONB operators (`->`, `->>`, `-`, `||`, `?`, etc.):
|
|
100
|
+
|
|
101
|
+
```sql
|
|
102
|
+
CREATE FUNCTION register_user(p_email TEXT, p_password TEXT, p_options JSON DEFAULT NULL)
|
|
103
|
+
RETURNS JSONB AS $$
|
|
104
|
+
DECLARE
|
|
105
|
+
v_insert_data JSONB;
|
|
106
|
+
BEGIN
|
|
107
|
+
v_insert_data := jsonb_build_object('email', p_email);
|
|
108
|
+
|
|
109
|
+
IF p_options IS NOT NULL THEN
|
|
110
|
+
-- Cast to JSONB for internal operations
|
|
111
|
+
v_insert_data := (p_options::jsonb - 'id' - 'password') || v_insert_data;
|
|
112
|
+
END IF;
|
|
113
|
+
|
|
114
|
+
-- ...
|
|
115
|
+
END;
|
|
116
|
+
$$ LANGUAGE plpgsql;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Table Columns: Use JSONB
|
|
120
|
+
|
|
121
|
+
Table columns should still use `JSONB` for efficient storage and indexing:
|
|
122
|
+
|
|
123
|
+
```sql
|
|
124
|
+
-- ✅ CORRECT - JSONB for table columns
|
|
125
|
+
CREATE TABLE users (
|
|
126
|
+
id SERIAL PRIMARY KEY,
|
|
127
|
+
metadata JSONB DEFAULT '{}' -- Efficient storage & indexing
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Summary
|
|
132
|
+
|
|
133
|
+
| Context | Type | Reason |
|
|
134
|
+
|---------|------|--------|
|
|
135
|
+
| Function input parameters | `JSON` | Easy to pass from JavaScript (`JSON.stringify()`) |
|
|
136
|
+
| Internal function operations | `::jsonb` cast | Access to JSONB operators |
|
|
137
|
+
| Table columns | `JSONB` | Efficient storage and indexing |
|
|
138
|
+
|
|
139
|
+
This pattern - **JSON for input parameters, JSONB for storage** - eliminates serialization confusion at the API boundary.
|
|
140
|
+
|
|
75
141
|
## Function Categories
|
|
76
142
|
|
|
77
143
|
### Public API Functions (No underscore)
|
package/package.json
CHANGED
|
@@ -69,7 +69,7 @@ $$;`;
|
|
|
69
69
|
-- p_options: optional JSON object with additional fields to set on the user record
|
|
70
70
|
-- Example: register_user('test@example.com', 'password', '{"name": "Test User"}')
|
|
71
71
|
-- ============================================================================
|
|
72
|
-
CREATE OR REPLACE FUNCTION register_user(p_email TEXT, p_password TEXT, p_options
|
|
72
|
+
CREATE OR REPLACE FUNCTION register_user(p_email TEXT, p_password TEXT, p_options JSON DEFAULT NULL)
|
|
73
73
|
RETURNS JSONB
|
|
74
74
|
LANGUAGE plpgsql
|
|
75
75
|
SECURITY DEFINER
|
|
@@ -85,9 +85,10 @@ BEGIN
|
|
|
85
85
|
v_hash := crypt(p_password, v_salt);
|
|
86
86
|
|
|
87
87
|
-- Build insert data: options fields + email + password_hash (options cannot override core fields)
|
|
88
|
+
-- Cast p_options to JSONB for internal operations (JSON type is for API boundary convenience)
|
|
88
89
|
v_insert_data := jsonb_build_object('email', p_email, 'password_hash', v_hash);
|
|
89
90
|
IF p_options IS NOT NULL THEN
|
|
90
|
-
v_insert_data := (p_options - 'id' - 'email' - 'password_hash' - 'password') || v_insert_data;
|
|
91
|
+
v_insert_data := (p_options::jsonb - 'id' - 'email' - 'password_hash' - 'password') || v_insert_data;
|
|
91
92
|
END IF;
|
|
92
93
|
|
|
93
94
|
-- Dynamic INSERT from JSONB (same pattern as compiled save functions)
|