Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions hub/procedures/channel/channel_export_count.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,49 @@ DELIMITER $

-- =========================================================
-- channel_export_count
-- Fast COUNT of hub team-chat messages (file_thread_id IS NULL)
-- for the given uid and optional date range. Used by the
-- 10k guard in channel.export before gathering begins.
-- Fast COUNT of team-chat messages (file_thread_id IS NULL)
-- for the given uid, optional date range, and folder subtree.
-- Used by the 10k guard in channel.export and the message
-- count shown on the export modal's folder card.
-- Date bounds arrive as VARCHAR: the mariadb layer converts a
-- JS null param to '' (empty string), which an INT(11) IN-param
-- rejects under strict SQL mode. Accept text, normalise '' / NULL
-- to a NULL bound (no filter) and CAST numeric strings to epoch.
-- Folder scope mirrors channel_export_messages: only messages
-- whose metadata._scope_nid falls inside the subtree rooted at
-- _root_nid are counted; legacy rows (no _scope_nid) always
-- count. _root_nid NULL/''/'0' = hub root (whole hub).
-- READ-ONLY: no UPDATE / INSERT.
-- =========================================================
DROP PROCEDURE IF EXISTS `channel_export_count`$
CREATE PROCEDURE `channel_export_count`(
IN _uid VARCHAR(16),
IN _root_nid VARCHAR(16),
IN _date_start VARCHAR(20),
IN _date_end VARCHAR(20)
)
BEGIN
DECLARE _root VARCHAR(16) DEFAULT NULL;
DECLARE ds BIGINT DEFAULT NULL;
DECLARE de BIGINT DEFAULT NULL;
IF _date_start IS NOT NULL AND _date_start <> '' THEN SET ds = CAST(_date_start AS UNSIGNED); END IF;
IF _date_end IS NOT NULL AND _date_end <> '' THEN SET de = CAST(_date_end AS UNSIGNED); END IF;

IF _root_nid IS NOT NULL AND _root_nid <> '' AND _root_nid <> '0' THEN
SELECT id INTO _root FROM media WHERE id = _root_nid LIMIT 1;
END IF;
IF _root IS NULL THEN
SELECT id INTO _root FROM media WHERE parent_id = '0' LIMIT 1;
END IF;

WITH RECURSIVE subtree AS (
SELECT m.id FROM media m WHERE m.id = _root
UNION ALL
SELECT c.id
FROM media c
INNER JOIN subtree s ON c.parent_id = s.id
WHERE c.mimetype = 'folder' AND c.status = 'active'
)
SELECT COUNT(*) AS message_count
FROM channel c
WHERE
Expand All @@ -32,7 +54,11 @@ BEGIN
WHERE uid = _uid AND ref_sys_id = c.sys_id
)
AND (ds IS NULL OR c.ctime >= ds)
AND (de IS NULL OR c.ctime <= de);
AND (de IS NULL OR c.ctime <= de)
AND (
read_json_object(c.metadata, '_scope_nid') = ''
OR read_json_object(c.metadata, '_scope_nid') IN (SELECT id FROM subtree)
);
END $

DELIMITER ;
39 changes: 35 additions & 4 deletions hub/procedures/channel/channel_export_file_thread_list.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,55 @@ DELIMITER $

-- =========================================================
-- channel_export_file_thread_list
-- Hub-wide list of active file threads with resolved filename.
-- Used by channel.export_scope to enumerate all file threads
-- the user may include in an export. Single-hub DB context.
-- List active file threads for chat export, restricted to
-- files living inside the folder subtree rooted at _root_nid
-- (current membership follows media.parent_id, matching
-- channel_file_thread_list_by_folder). _root_nid NULL/''/'0'
-- = hub root (whole hub).
-- Also returns the file's current folder (folder_nid +
-- folder_name) so export sections can label threads with
-- their location. Only active files — trashed files keep
-- their thread row but must not appear in the export scope.
-- Used by channel.export_scope and the export gather.
-- No pagination — export scope UI renders the full list once.
-- READ-ONLY.
-- =========================================================
DROP PROCEDURE IF EXISTS `channel_export_file_thread_list`$
CREATE PROCEDURE `channel_export_file_thread_list`(
IN _uid VARCHAR(16)
IN _uid VARCHAR(16),
IN _root_nid VARCHAR(16)
)
BEGIN
DECLARE _root VARCHAR(16) DEFAULT NULL;

IF _root_nid IS NOT NULL AND _root_nid <> '' AND _root_nid <> '0' THEN
SELECT id INTO _root FROM media WHERE id = _root_nid LIMIT 1;
END IF;
IF _root IS NULL THEN
SELECT id INTO _root FROM media WHERE parent_id = '0' LIMIT 1;
END IF;

WITH RECURSIVE subtree AS (
SELECT m.id FROM media m WHERE m.id = _root
UNION ALL
SELECT c.id
FROM media c
INNER JOIN subtree s ON c.parent_id = s.id
WHERE c.mimetype = 'folder' AND c.status = 'active'
)
SELECT
ft.root_message_id AS file_thread_id,
ft.file_nid,
m.user_filename AS filename,
m.parent_id AS folder_nid,
f.user_filename AS folder_name,
ft.reply_count
FROM file_thread ft
INNER JOIN media m ON m.id = ft.file_nid
LEFT JOIN media f ON f.id = m.parent_id
WHERE ft.status = 'active'
AND m.status = 'active'
AND m.parent_id IN (SELECT id FROM subtree)
ORDER BY ft.mtime DESC;
END $

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ BEGIN
c.metadata,
COALESCE(d.firstname, du.name, '') AS firstname,
COALESCE(d.lastname, '') AS lastname,
COALESCE(CONCAT(d.firstname, ' ', d.lastname), du.name, '') AS fullname,
TRIM(COALESCE(NULLIF(CONCAT_WS(' ', d.firstname, d.lastname), ''), du.name, '')) AS fullname,
IFNULL(read_json_object(c.metadata, 'message_type'), 'chat') AS message_type,
read_json_object(c.metadata, 'call_status') AS call_status
FROM (
Expand Down
63 changes: 63 additions & 0 deletions hub/procedures/channel/channel_export_folder_tree.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
DELIMITER $

-- =========================================================
-- channel_export_folder_tree
-- Folder subtree for chat export, rooted at _root_nid.
-- Chat export groups messages into one section per folder
-- (messages carry their folder in metadata._scope_nid), so the
-- export needs the list of folders under the exported folder.
--
-- _root_nid: the folder the export modal was opened in. NULL /
-- '' / '0' resolves to the hub root node (parent_id='0').
-- _hub_id: used only to resolve the display name of the hub
-- root, whose media row has an empty user_filename — the
-- name lives in yp.hub (name, falling back to hubname).
--
-- System folders (__chat__, __trash__, __upload__) never host
-- user chat and are pruned together with their subtrees.
-- READ-ONLY.
-- =========================================================
DROP PROCEDURE IF EXISTS `channel_export_folder_tree`$
CREATE PROCEDURE `channel_export_folder_tree`(
IN _hub_id VARCHAR(16),
IN _root_nid VARCHAR(16)
)
BEGIN
DECLARE _root VARCHAR(16) DEFAULT NULL;

IF _root_nid IS NOT NULL AND _root_nid <> '' AND _root_nid <> '0' THEN
SELECT id INTO _root FROM media WHERE id = _root_nid LIMIT 1;
END IF;
IF _root IS NULL THEN
SELECT id INTO _root FROM media WHERE parent_id = '0' LIMIT 1;
END IF;

WITH RECURSIVE subtree AS (
SELECT m.id, m.parent_id, m.user_filename, 0 AS depth
FROM media m
WHERE m.id = _root
UNION ALL
SELECT c.id, c.parent_id, c.user_filename, s.depth + 1
FROM media c
INNER JOIN subtree s ON c.parent_id = s.id
WHERE c.mimetype = 'folder'
AND c.status = 'active'
AND c.user_filename NOT IN ('__chat__', '__trash__', '__upload__')
)
SELECT
s.id,
s.parent_id,
s.depth,
CASE
WHEN s.depth = 0 AND (s.user_filename IS NULL OR s.user_filename = '')
THEN (
SELECT COALESCE(NULLIF(h.name, ''), NULLIF(h.hubname, ''), _hub_id)
FROM yp.hub h WHERE h.id = _hub_id LIMIT 1
)
ELSE s.user_filename
END AS name
FROM subtree s
ORDER BY s.depth ASC, s.user_filename ASC;
END $

DELIMITER ;
39 changes: 35 additions & 4 deletions hub/procedures/channel/channel_export_messages.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,51 @@ DELIMITER $
-- full history when client omits dates). Bounds arrive as
-- VARCHAR because the mariadb layer sends '' for a JS null
-- param, which an INT(11) IN-param rejects in strict mode.
-- 3. ORDER BY ctime ASC (export order, oldest first).
-- 4. No _sort_by / _order params — always ascending ctime.
-- 3. ORDER BY sys_id ASC (export order, oldest first).
-- 4. No _sort_by / _order params — always ascending.
-- 5. Folder-subtree scope: general-chat messages carry their
-- folder in metadata._scope_nid; only rows whose folder is
-- inside the subtree rooted at _root_nid are returned.
-- Legacy rows (no _scope_nid — the live UI shows them in
-- every folder context) are always included; the service
-- groups them into the export-root section.
-- _root_nid NULL/''/'0' = hub root (whole hub).
-- 6. scope_nid exposed as a column so the service can group
-- messages into one section per folder.
-- =========================================================
DROP PROCEDURE IF EXISTS `channel_export_messages`$
CREATE PROCEDURE `channel_export_messages`(
IN _uid VARCHAR(16),
IN _root_nid VARCHAR(16),
IN _date_start VARCHAR(20),
IN _date_end VARCHAR(20),
IN _page TINYINT(4)
)
BEGIN
DECLARE _range BIGINT;
DECLARE _offset BIGINT;
DECLARE _root VARCHAR(16) DEFAULT NULL;
DECLARE ds BIGINT DEFAULT NULL;
DECLARE de BIGINT DEFAULT NULL;
IF _date_start IS NOT NULL AND _date_start <> '' THEN SET ds = CAST(_date_start AS UNSIGNED); END IF;
IF _date_end IS NOT NULL AND _date_end <> '' THEN SET de = CAST(_date_end AS UNSIGNED); END IF;
CALL pageToLimits(_page, _offset, _range);

IF _root_nid IS NOT NULL AND _root_nid <> '' AND _root_nid <> '0' THEN
SELECT id INTO _root FROM media WHERE id = _root_nid LIMIT 1;
END IF;
IF _root IS NULL THEN
SELECT id INTO _root FROM media WHERE parent_id = '0' LIMIT 1;
END IF;

WITH RECURSIVE subtree AS (
SELECT m.id FROM media m WHERE m.id = _root
UNION ALL
SELECT c.id
FROM media c
INNER JOIN subtree s ON c.parent_id = s.id
WHERE c.mimetype = 'folder' AND c.status = 'active'
)
SELECT
_page AS `page`,
c.sys_id,
Expand All @@ -45,12 +71,13 @@ BEGIN
c.status,
c.ctime,
c.metadata,
read_json_object(c.metadata, '_scope_nid') AS scope_nid,
IFNULL(read_json_object(c.metadata, 'message_type'), 'chat') AS message_type,
COALESCE(d.firstname, du.name, '') AS firstname,
COALESCE(d.lastname, '') AS lastname,
COALESCE(CONCAT(d.firstname, ' ', d.lastname), du.name, '') AS fullname
TRIM(COALESCE(NULLIF(CONCAT_WS(' ', d.firstname, d.lastname), ''), du.name, '')) AS fullname
FROM (
SELECT sys_id FROM channel c
SELECT c.sys_id FROM channel c
WHERE
NOT EXISTS (
SELECT 1 FROM delete_channel
Expand All @@ -59,6 +86,10 @@ BEGIN
AND c.file_thread_id IS NULL
AND (ds IS NULL OR c.ctime >= ds)
AND (de IS NULL OR c.ctime <= de)
AND (
read_json_object(c.metadata, '_scope_nid') = ''
OR read_json_object(c.metadata, '_scope_nid') IN (SELECT id FROM subtree)
)
ORDER BY c.sys_id ASC
LIMIT _offset, _range
) s
Expand Down