Skip to content

Commit 5c4411a

Browse files
committed
feat: extract common subqueries
1 parent 0e1e3ad commit 5c4411a

File tree

1 file changed

+181
-154
lines changed

1 file changed

+181
-154
lines changed

catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/database/dao/proposals_v2_dao.dart

Lines changed: 181 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,43 @@ class DriftProposalsV2Dao extends DatabaseAccessor<DriftCatalystDatabase>
544544
return input.replaceAll("'", "''");
545545
}
546546

547+
/// Returns the SQL subquery for counting comments on a proposal.
548+
String _getCommentsCountSubquery() {
549+
return '''
550+
(
551+
SELECT COUNT(*)
552+
FROM documents_v2 c
553+
WHERE c.ref_id = p.id AND c.ref_ver = p.ver AND c.type = ?
554+
) as comments_count
555+
''';
556+
}
557+
558+
/// Returns the SQL for common JOINs used in proposal queries.
559+
///
560+
/// Includes:
561+
/// - `documents_local_metadata` for favorites
562+
/// - `documents_v2` alias 'origin' for original authors (first version)
563+
/// - `documents_v2` alias 't' for template
564+
String _getCommonJoins() {
565+
return '''
566+
LEFT JOIN documents_local_metadata dlm ON p.id = dlm.id
567+
LEFT JOIN documents_v2 origin ON p.id = origin.id AND origin.id = origin.ver AND origin.type = ?
568+
LEFT JOIN documents_v2 t ON p.template_id = t.id AND p.template_ver = t.ver AND t.type = ?
569+
''';
570+
}
571+
572+
/// Returns the SQL SELECT columns from common JOINs.
573+
///
574+
/// Includes:
575+
/// - `origin_authors`: Authors from the first version (origin table)
576+
/// - `is_favorite`: Favorite status from local metadata
577+
String _getCommonSelectColumns() {
578+
return '''
579+
origin.authors as origin_authors,
580+
COALESCE(dlm.is_favorite, 0) as is_favorite
581+
''';
582+
}
583+
547584
/// Returns the Common Table Expression (CTE) string defining "Effective Proposals".
548585
///
549586
/// **CTE Stages:**
@@ -630,6 +667,21 @@ class DriftProposalsV2Dao extends DatabaseAccessor<DriftCatalystDatabase>
630667
.trim();
631668
}
632669

670+
/// Returns the SQL subquery for getting all version IDs of a proposal.
671+
String _getVersionIdsSubquery() {
672+
return '''
673+
(
674+
SELECT GROUP_CONCAT(v_list.ver, ',')
675+
FROM (
676+
SELECT ver
677+
FROM documents_v2 v_sub
678+
WHERE v_sub.id = p.id AND v_sub.type = ?
679+
ORDER BY v_sub.ver ASC
680+
) v_list
681+
) as version_ids_str
682+
''';
683+
}
684+
633685
/// Processes a database row from [getCollaboratorsActions] query.
634686
Map<String, RawProposalCollaboratorsActions> _processCollaboratorsActions(
635687
List<TypedResult> rows,
@@ -680,6 +732,123 @@ class DriftProposalsV2Dao extends DatabaseAccessor<DriftCatalystDatabase>
680732
return tempMap.map((key, value) => MapEntry(key, RawProposalCollaboratorsActions(value)));
681733
}
682734

735+
/// Internal query to fetch a single proposal by [DocumentRef].
736+
///
737+
/// Uses the [_getValidActionsCTE] to resolve action status:
738+
/// - Checks latest action (any version) first - if 'hide', returns 'hide'
739+
/// - Otherwise gets action for specific version to determine draft/final status
740+
///
741+
// TODO(LynxLynxx): For hidden proposals, consider optimizing by not fetching
742+
// all data (template, comments, versions, etc.) since UI may only need to
743+
// show "proposal is hidden". This would require RawProposalEntity to support
744+
// default/empty values for its fields or a separate HiddenProposalEntity.
745+
Selectable<RawProposalEntity> _queryProposal(DocumentRef ref) {
746+
final proposalColumns = _buildPrefixedColumns('p', 'p');
747+
final templateColumns = _buildPrefixedColumns('t', 't');
748+
final validActionsCTE = _getValidActionsCTE();
749+
final versionIdsSubquery = _getVersionIdsSubquery();
750+
final commentsCountSubquery = _getCommentsCountSubquery();
751+
final commonJoins = _getCommonJoins();
752+
final commonSelectColumns = _getCommonSelectColumns();
753+
754+
final query =
755+
'''
756+
WITH $validActionsCTE
757+
SELECT
758+
$proposalColumns,
759+
$templateColumns,
760+
761+
-- First check if latest action (any version) is 'hide'
762+
-- If hidden, return 'hide'; otherwise get action for THIS specific version
763+
COALESCE(
764+
(
765+
SELECT
766+
CASE
767+
WHEN COALESCE(json_extract(va_latest.content, '\$.action'), 'draft') = 'hide'
768+
THEN 'hide'
769+
ELSE NULL
770+
END
771+
FROM valid_actions va_latest
772+
WHERE va_latest.ref_id = p.id
773+
ORDER BY va_latest.ver DESC LIMIT 1
774+
),
775+
(
776+
SELECT COALESCE(json_extract(va.content, '\$.action'), 'draft')
777+
FROM valid_actions va
778+
WHERE va.ref_id = p.id AND va.ref_ver = p.ver
779+
ORDER BY va.ver DESC LIMIT 1
780+
),
781+
'draft'
782+
) as action_type,
783+
$versionIdsSubquery,
784+
$commentsCountSubquery,
785+
$commonSelectColumns
786+
FROM documents_v2 p
787+
$commonJoins
788+
WHERE p.id = ? AND p.ver = ? AND p.type = ?
789+
''';
790+
791+
return customSelect(
792+
query,
793+
variables: [
794+
// CTE Variable
795+
Variable.withString(DocumentType.proposalActionDocument.uuid),
796+
// Subquery Variables
797+
Variable.withString(DocumentType.proposalDocument.uuid),
798+
Variable.withString(DocumentType.commentDocument.uuid),
799+
// Main Join Variables
800+
Variable.withString(DocumentType.proposalDocument.uuid),
801+
Variable.withString(DocumentType.proposalTemplate.uuid),
802+
// WHERE clause
803+
Variable.withString(ref.id),
804+
Variable.withString(ref.ver ?? ''),
805+
Variable.withString(DocumentType.proposalDocument.uuid),
806+
],
807+
readsFrom: {
808+
documentsV2,
809+
documentsLocalMetadata,
810+
documentAuthors,
811+
},
812+
).map((row) {
813+
final proposalData = {
814+
for (final col in documentsV2.$columns)
815+
col.$name: row.readNullableWithType(col.type, 'p_${col.$name}'),
816+
};
817+
final proposal = documentsV2.map(proposalData);
818+
819+
final templateData = {
820+
for (final col in documentsV2.$columns)
821+
col.$name: row.readNullableWithType(col.type, 't_${col.$name}'),
822+
};
823+
824+
final template = templateData['id'] != null ? documentsV2.map(templateData) : null;
825+
826+
final actionTypeRaw = row.readNullable<String>('action_type') ?? '';
827+
final actionType =
828+
ProposalSubmissionActionDto.fromJson(actionTypeRaw)?.toModel() ??
829+
ProposalSubmissionAction.draft;
830+
831+
final versionIdsRaw = row.readNullable<String>('version_ids_str') ?? '';
832+
final versionIds = versionIdsRaw.split(',');
833+
834+
final commentsCount = row.readNullable<int>('comments_count') ?? 0;
835+
final isFavorite = (row.readNullable<int>('is_favorite') ?? 0) == 1;
836+
837+
final originalAuthorsRaw = row.readNullable<String>('origin_authors');
838+
final originalAuthors = DocumentConverters.catId.fromSql(originalAuthorsRaw ?? '');
839+
840+
return RawProposalEntity(
841+
proposal: proposal,
842+
template: template,
843+
actionType: actionType,
844+
versionIds: versionIds,
845+
commentsCount: commentsCount,
846+
isFavorite: isFavorite,
847+
originalAuthors: originalAuthors,
848+
);
849+
});
850+
}
851+
683852
/// Internal query to calculate total ask.
684853
///
685854
/// Similar to the main CTE but filters specifically for `effective_final_proposals`.
@@ -781,37 +950,24 @@ class DriftProposalsV2Dao extends DatabaseAccessor<DriftCatalystDatabase>
781950
final whereClause = filterClauses.isEmpty ? '' : 'AND ${filterClauses.join(' AND ')}';
782951

783952
final effectiveProposals = _getEffectiveProposalsCTE();
953+
final versionIdsSubquery = _getVersionIdsSubquery();
954+
final commentsCountSubquery = _getCommentsCountSubquery();
955+
final commonJoins = _getCommonJoins();
956+
final commonSelectColumns = _getCommonSelectColumns();
957+
784958
final cteQuery =
785959
'''
786960
WITH $effectiveProposals
787-
SELECT
788-
$proposalColumns,
789-
$templateColumns,
961+
SELECT
962+
$proposalColumns,
963+
$templateColumns,
790964
ep.action_type,
791-
792-
(
793-
SELECT GROUP_CONCAT(v_list.ver, ',')
794-
FROM (
795-
SELECT ver
796-
FROM documents_v2 v_sub
797-
WHERE v_sub.id = p.id AND v_sub.type = ?
798-
ORDER BY v_sub.ver ASC
799-
) v_list
800-
) as version_ids_str,
801-
802-
(
803-
SELECT COUNT(*)
804-
FROM documents_v2 c
805-
WHERE c.ref_id = p.id AND c.ref_ver = p.ver AND c.type = ?
806-
) as comments_count,
807-
808-
origin.authors as origin_authors,
809-
COALESCE(dlm.is_favorite, 0) as is_favorite
965+
$versionIdsSubquery,
966+
$commentsCountSubquery,
967+
$commonSelectColumns
810968
FROM documents_v2 p
811969
INNER JOIN effective_proposals ep ON p.id = ep.id AND p.ver = ep.ver
812-
LEFT JOIN documents_local_metadata dlm ON p.id = dlm.id
813-
LEFT JOIN documents_v2 origin ON p.id = origin.id AND origin.id = origin.ver AND origin.type = ?
814-
LEFT JOIN documents_v2 t ON p.template_id = t.id AND p.template_ver = t.ver AND t.type = ?
970+
$commonJoins
815971
WHERE p.type = ? $whereClause
816972
ORDER BY $orderByClause
817973
LIMIT ? OFFSET ?
@@ -881,135 +1037,6 @@ class DriftProposalsV2Dao extends DatabaseAccessor<DriftCatalystDatabase>
8811037
});
8821038
}
8831039

884-
/// Internal query to fetch a single proposal by [DocumentRef].
885-
///
886-
/// Uses the [_getValidActionsCTE] to resolve action status:
887-
/// - Checks latest action (any version) first - if 'hide', returns 'hide'
888-
/// - Otherwise gets action for specific version to determine draft/final status
889-
///
890-
// TODO(LynxLynxx): For hidden proposals, consider optimizing by not fetching
891-
// all data (template, comments, versions, etc.) since UI may only need to
892-
// show "proposal is hidden". This would require RawProposalEntity to support
893-
// default/empty values for its fields or a separate HiddenProposalEntity.
894-
Selectable<RawProposalEntity> _queryProposal(DocumentRef ref) {
895-
final proposalColumns = _buildPrefixedColumns('p', 'p');
896-
final templateColumns = _buildPrefixedColumns('t', 't');
897-
898-
final validActionsCTE = _getValidActionsCTE();
899-
final query = '''
900-
WITH $validActionsCTE
901-
SELECT
902-
$proposalColumns,
903-
$templateColumns,
904-
905-
-- First check if latest action (any version) is 'hide'
906-
-- If hidden, return 'hide'; otherwise get action for THIS specific version
907-
COALESCE(
908-
(
909-
SELECT
910-
CASE
911-
WHEN COALESCE(json_extract(va_latest.content, '\$.action'), 'draft') = 'hide'
912-
THEN 'hide'
913-
ELSE NULL
914-
END
915-
FROM valid_actions va_latest
916-
WHERE va_latest.ref_id = p.id
917-
ORDER BY va_latest.ver DESC LIMIT 1
918-
),
919-
(
920-
SELECT COALESCE(json_extract(va.content, '\$.action'), 'draft')
921-
FROM valid_actions va
922-
WHERE va.ref_id = p.id AND va.ref_ver = p.ver
923-
ORDER BY va.ver DESC LIMIT 1
924-
),
925-
'draft'
926-
) as action_type,
927-
928-
(
929-
SELECT GROUP_CONCAT(v_list.ver, ',')
930-
FROM (
931-
SELECT ver
932-
FROM documents_v2 v_sub
933-
WHERE v_sub.id = p.id AND v_sub.type = ?
934-
ORDER BY v_sub.ver ASC
935-
) v_list
936-
) as version_ids_str,
937-
938-
(
939-
SELECT COUNT(*)
940-
FROM documents_v2 c
941-
WHERE c.ref_id = p.id AND c.ref_ver = p.ver AND c.type = ?
942-
) as comments_count,
943-
944-
origin.authors as origin_authors,
945-
COALESCE(dlm.is_favorite, 0) as is_favorite
946-
FROM documents_v2 p
947-
LEFT JOIN documents_local_metadata dlm ON p.id = dlm.id
948-
LEFT JOIN documents_v2 origin ON p.id = origin.id AND origin.id = origin.ver AND origin.type = ?
949-
LEFT JOIN documents_v2 t ON p.template_id = t.id AND p.template_ver = t.ver AND t.type = ?
950-
WHERE p.id = ? AND p.ver = ? AND p.type = ?
951-
''';
952-
953-
return customSelect(
954-
query,
955-
variables: [
956-
// CTE Variable
957-
Variable.withString(DocumentType.proposalActionDocument.uuid),
958-
// Subquery Variables
959-
Variable.withString(DocumentType.proposalDocument.uuid),
960-
Variable.withString(DocumentType.commentDocument.uuid),
961-
// Main Join Variables
962-
Variable.withString(DocumentType.proposalDocument.uuid),
963-
Variable.withString(DocumentType.proposalTemplate.uuid),
964-
// WHERE clause
965-
Variable.withString(ref.id),
966-
Variable.withString(ref.ver ?? ''),
967-
Variable.withString(DocumentType.proposalDocument.uuid),
968-
],
969-
readsFrom: {
970-
documentsV2,
971-
documentsLocalMetadata,
972-
documentAuthors,
973-
},
974-
).map((row) {
975-
final proposalData = {
976-
for (final col in documentsV2.$columns)
977-
col.$name: row.readNullableWithType(col.type, 'p_${col.$name}'),
978-
};
979-
final proposal = documentsV2.map(proposalData);
980-
981-
final templateData = {
982-
for (final col in documentsV2.$columns)
983-
col.$name: row.readNullableWithType(col.type, 't_${col.$name}'),
984-
};
985-
986-
final template = templateData['id'] != null ? documentsV2.map(templateData) : null;
987-
988-
final actionTypeRaw = row.readNullable<String>('action_type') ?? '';
989-
final actionType = ProposalSubmissionActionDto.fromJson(actionTypeRaw)?.toModel() ??
990-
ProposalSubmissionAction.draft;
991-
992-
final versionIdsRaw = row.readNullable<String>('version_ids_str') ?? '';
993-
final versionIds = versionIdsRaw.split(',');
994-
995-
final commentsCount = row.readNullable<int>('comments_count') ?? 0;
996-
final isFavorite = (row.readNullable<int>('is_favorite') ?? 0) == 1;
997-
998-
final originalAuthorsRaw = row.readNullable<String>('origin_authors');
999-
final originalAuthors = DocumentConverters.catId.fromSql(originalAuthorsRaw ?? '');
1000-
1001-
return RawProposalEntity(
1002-
proposal: proposal,
1003-
template: template,
1004-
actionType: actionType,
1005-
versionIds: versionIds,
1006-
commentsCount: commentsCount,
1007-
isFavorite: isFavorite,
1008-
originalAuthors: originalAuthors,
1009-
);
1010-
});
1011-
}
1012-
10131040
bool _shouldReturnEarlyFor({
10141041
required ProposalsFiltersV2 filters,
10151042
int? size,

0 commit comments

Comments
 (0)