Skip to content

Commit 1dc058f

Browse files
committed
Refactor and fix broken relation truncation and content_length+content array truncation in relation loading.
1 parent 3abacd9 commit 1dc058f

File tree

2 files changed

+52
-36
lines changed

2 files changed

+52
-36
lines changed

src/manager/mod.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,7 @@ impl Manager {
140140

141141
let types_json =
142142
serde_json::to_string(&rel_query.types).unwrap_or_else(|_| "[]".to_string());
143-
let tags_json =
144-
serde_json::to_string(&rel_query.tags).unwrap_or_else(|_| "[]".to_string());
143+
let tags_json = serde_json::to_string(&rel_query.tags).unwrap_or_else(|_| "[]".to_string());
145144

146145
let rel_entries: Vec<Entry> = sqlx::query_as(&q.search_relations.query)
147146
.bind(&id_json)
@@ -150,6 +149,7 @@ impl Manager {
150149
.bind(&tags_json)
151150
.bind(&rel_query.status)
152151
.bind(rel_query.max_per_type)
152+
.bind(rel_query.max_content_items)
153153
.fetch_all(&self.db)
154154
.await?;
155155

@@ -172,16 +172,10 @@ impl Manager {
172172
}
173173
}
174174

175-
// Retain the total_relations count and truncate relations.
175+
// Set total_relations from query results (computed per from_id via window function).
176176
for e in entries.iter_mut() {
177-
e.total_relations = e.relations.len() as i32;
178-
179-
if rel_query.max_content_items > 0 {
180-
for rel in &mut e.relations {
181-
if rel.content.len() > rel_query.max_content_items as usize {
182-
rel.content.0.truncate(rel_query.max_content_items as usize);
183-
}
184-
}
177+
if let Some(first_rel) = e.relations.first() {
178+
e.total_relations = first_rel.total_relations;
185179
}
186180
}
187181

static/sql/queries.sql

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,52 @@ LIMIT $6 OFFSET $5;
2222

2323
-- name: search-relations
2424
-- Load relations for a set of entry IDs.
25-
-- $1: entry IDs (JSON array), $2: to_lang, $3: types (JSON array), $4: tags (JSON array), $5: status, $6: max per type
26-
SELECT e.*,
25+
-- $1: entry IDs (JSON array), $2: to_lang, $3: types (JSON array), $4: tags (JSON array),
26+
-- $5: status, $6: max per type, $7: max content items (0 = no truncation)
27+
SELECT e.id, e.guid, e.initial, e.weight, e.tokens, e.lang,
28+
e.tags, e.phones, e.notes, e.meta, e.status, e.created_at, e.updated_at,
29+
-- Truncate content array if $7 > 0
30+
CASE WHEN $7 > 0
31+
THEN (SELECT JSON_GROUP_ARRAY(value) FROM (SELECT value FROM JSON_EACH(e.content) LIMIT $7))
32+
ELSE e.content
33+
END AS content,
2734
JSON_ARRAY_LENGTH(e.content) AS content_length,
28-
r.from_id,
29-
r.id AS relation_id,
30-
r.types AS relation_types,
31-
r.tags AS relation_tags,
32-
r.notes AS relation_notes,
33-
r.weight AS relation_weight,
34-
r.status AS relation_status,
35-
r.created_at AS relation_created_at,
36-
r.updated_at AS relation_updated_at
35+
sub.from_id,
36+
sub.relation_id,
37+
sub.relation_types,
38+
sub.relation_tags,
39+
sub.relation_notes,
40+
sub.relation_weight,
41+
sub.relation_status,
42+
sub.relation_created_at,
43+
sub.relation_updated_at,
44+
sub.total_relations
3745
FROM entries e
38-
INNER JOIN relations r ON r.to_id = e.id
39-
WHERE r.from_id IN (SELECT value FROM json_each($1))
40-
AND ($2 = '' OR e.lang = $2)
41-
AND ($5 = '' OR r.status = $5)
42-
AND ($3 = '[]' OR EXISTS (
43-
SELECT 1 FROM json_each(r.types) rt, json_each($3) qt WHERE rt.value = qt.value
44-
))
45-
AND ($4 = '[]' OR EXISTS (
46-
SELECT 1 FROM json_each(r.tags) rt, json_each($4) qt WHERE rt.value = qt.value
47-
))
48-
ORDER BY r.from_id, r.types, r.weight;
46+
INNER JOIN (
47+
SELECT r.to_id,
48+
r.from_id,
49+
r.id AS relation_id,
50+
r.types AS relation_types,
51+
r.tags AS relation_tags,
52+
r.notes AS relation_notes,
53+
r.weight AS relation_weight,
54+
r.status AS relation_status,
55+
r.created_at AS relation_created_at,
56+
r.updated_at AS relation_updated_at,
57+
ROW_NUMBER() OVER (PARTITION BY r.from_id, r.types ORDER BY r.weight) AS rn,
58+
COUNT(*) OVER (PARTITION BY r.from_id) AS total_relations
59+
FROM relations r
60+
WHERE r.from_id IN (SELECT value FROM JSON_EACH($1))
61+
AND ($5 = '' OR r.status = $5)
62+
AND ($3 = '[]' OR EXISTS (
63+
SELECT 1 FROM JSON_EACH(r.types) rt, JSON_EACH($3) qt WHERE rt.value = qt.value
64+
))
65+
AND ($4 = '[]' OR EXISTS (
66+
SELECT 1 FROM JSON_EACH(r.tags) rt, JSON_EACH($4) qt WHERE rt.value = qt.value
67+
))
68+
) sub ON sub.to_id = e.id AND ($6 = 0 OR sub.rn <= $6)
69+
WHERE ($2 = '' OR e.lang = $2)
70+
ORDER BY sub.from_id, sub.relation_types, sub.relation_weight;
4971

5072
-- name: get-entry
5173
SELECT *, JSON_ARRAY_LENGTH(content) AS content_length FROM entries WHERE
@@ -118,10 +140,10 @@ DELETE FROM relations WHERE id = $1;
118140
-- Update weights based on array position.
119141
UPDATE relations SET weight = (
120142
SELECT idx FROM (
121-
SELECT value, row_number() OVER () AS idx FROM json_each($1)
143+
SELECT value, row_number() OVER () AS idx FROM JSON_EACH($1)
122144
) WHERE value = relations.id
123145
)
124-
WHERE id IN (SELECT value FROM json_each($1));
146+
WHERE id IN (SELECT value FROM JSON_EACH($1));
125147

126148
-- name: get-stats
127149
SELECT json_object(
@@ -162,7 +184,7 @@ INSERT INTO relations (from_id, to_id, types, tags, notes, weight, status)
162184
WHERE NOT EXISTS (
163185
SELECT 1 FROM relations
164186
WHERE from_id = $1 AND to_id = $2
165-
AND EXISTS (SELECT 1 FROM json_each(types) rt, json_each($3) nt WHERE rt.value = nt.value)
187+
AND EXISTS (SELECT 1 FROM JSON_EACH(types) rt, JSON_EACH($3) nt WHERE rt.value = nt.value)
166188
)
167189
RETURNING id;
168190

0 commit comments

Comments
 (0)