Skip to content

Conversation

@pcapriotti
Copy link
Contributor

@pcapriotti pcapriotti commented Oct 10, 2025

In preparation for channel search, this PR introduces a query builder DSL to help construct dynamic postgres queries like those for searching.

It also refactors the existing user group search code to use the DSL.

Checklist

  • Add a new entry in an appropriate subdirectory of changelog.d
  • Read and follow the PR guidelines

@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Oct 10, 2025
@pcapriotti pcapriotti marked this pull request as ready for review October 10, 2025 07:26
@pcapriotti pcapriotti requested review from a team as code owners October 10, 2025 07:26
Copy link
Contributor

@blackheaven blackheaven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer using dedicated eDSLs such as esqueleto, but it least it simplifies things.

}

-- | Construct a WHERE clause from a list of fragments.
where_ :: [QueryFragment] -> QueryFragment
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If frags is empty this might produce an invalid query, no? Of course, it's the callers' responsibility, but this would be an easy safeguard, IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but this is not meant to produce only valid queries. You can also write nonsense in literal fragments. So I don't really see the point in adding these checks.

clause1 :: forall a. (PostgresValue a) => Text -> Text -> a -> QueryFragment
clause1 field op value = clause op (mkClause field value)

orderBy :: [(Text, SortOrder)] -> QueryFragment
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same problem as above with where_.

@battermann battermann requested a review from Copilot October 10, 2025 08:06
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a query builder DSL for constructing dynamic PostgreSQL queries to support channel search functionality. The DSL provides a composable way to build SQL statements with proper parameter encoding and reduces code duplication in database query construction.

  • Introduces a new Wire.Postgres module with a query builder DSL for constructing PostgreSQL statements
  • Refactors the user group search functionality to use the new DSL instead of manual query construction
  • Generalizes pagination state handling to support different entity types

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
libs/wire-subsystems/src/Wire/Postgres.hs New module implementing the query builder DSL with fragment composition and parameter encoding
libs/wire-subsystems/src/Wire/PaginationState.hs Generalized pagination state type to work with different ID types
libs/wire-subsystems/src/Wire/UserGroupSubsystem.hs Replaces multiple individual parameters with a GroupSearch data structure
libs/wire-subsystems/src/Wire/UserGroupSubsystem/Interpreter.hs Updates to use the new GroupSearch structure and pagination state
libs/wire-subsystems/src/Wire/UserGroupStore/Postgres.hs Refactored to use the query builder DSL instead of manual SQL construction
libs/wire-subsystems/src/Wire/UserGroupStore.hs Updates pagination state type to be generic and changes time handling
services/brig/src/Brig/API/Public.hs Updates API layer to construct GroupSearch structure
libs/wire-subsystems/test/unit/Wire/UserGroupSubsystem/InterpreterSpec.hs Test updates to use new GroupSearch structure with def
libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserGroupStore.hs Mock implementation updates for type conversion functions

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

-- > <> limit (10 :: Int)
-- > in buildStatement q userDecoder
--
-- Not that the encoders are specialised to the specific values passed when
Copy link

Copilot AI Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'Not' to 'Note'

Suggested change
-- Not that the encoders are specialised to the specific values passed when
-- Note that the encoders are specialised to the specific values passed when

Copilot uses AI. Check for mistakes.
@pcapriotti pcapriotti changed the base branch from conversation-postgres to develop October 13, 2025 08:58
@pcapriotti pcapriotti merged commit e77e1f9 into develop Oct 14, 2025
9 checks passed
@pcapriotti pcapriotti deleted the query-builder branch October 14, 2025 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants