Skip to content

Commit

Permalink
Refactor pagination SQL queries to use generic parameters
Browse files Browse the repository at this point in the history
Change type signatures to use generic `q` type with `ToRow` constraint instead of `[Action]`
  • Loading branch information
rvarun11 committed Dec 23, 2024
1 parent dbd7bb5 commit cb1ab44
Showing 1 changed file with 18 additions and 22 deletions.
40 changes: 18 additions & 22 deletions IHP/Pagination/ControllerFunctions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,12 @@ module IHP.Pagination.ControllerFunctions
import IHP.Prelude
import IHP.Controller.Context
import IHP.Controller.Param ( paramOrDefault, paramOrNothing )

import IHP.Pagination.Types
( Options(..), Pagination(..) )

import IHP.QueryBuilder
( HasQueryBuilder, filterWhereILike, limit, offset )
import IHP.Pagination.Types ( Options(..), Pagination(..) )
import IHP.QueryBuilder ( HasQueryBuilder, filterWhereILike, limit, offset )
import IHP.Fetch (fetchCount)

import IHP.ModelSupport (GetModelByTableName, sqlQuery, sqlQueryScalar, Table)

import Database.PostgreSQL.Simple.ToField (toField, Action)
import Database.PostgreSQL.Simple.Types (Query(Query))
import Database.PostgreSQL.Simple (FromRow, ToRow, Query(..), Only(Only), (:.)(..))

-- | Paginate a query, with the following default options:
--
Expand Down Expand Up @@ -173,18 +167,19 @@ defaultPaginationOptions =
--
-- __Example:__
--
-- > (users, pagination) <- paginatedSqlQuery @User "SELECT id, firstname, lastname FROM users" []
-- > (users, pagination) <- paginatedSqlQuery "SELECT id, firstname, lastname FROM users" ()
--
-- Take a look at "IHP.QueryBuilder" for a typesafe approach on building simple queries.
--
-- *AutoRefresh:* When using 'paginatedSqlQuery' with AutoRefresh, you need to use 'trackTableRead' to let AutoRefresh know that you have accessed a certain table. Otherwise AutoRefresh will not watch table of your custom sql query.
paginatedSqlQuery
:: forall model
. ( FromRow model
:: forall r q
. ( FromRow r
, ToRow q
, ?context :: ControllerContext
, ?modelContext :: ModelContext
)
=> ByteString -> [Action] -> IO ([model], Pagination)
=> Query -> q -> IO ([r], Pagination)
paginatedSqlQuery = paginatedSqlQueryWithOptions defaultPaginationOptions

-- | Runs a raw sql query and adds pagination to it.
Expand All @@ -193,23 +188,24 @@ paginatedSqlQuery = paginatedSqlQueryWithOptions defaultPaginationOptions
--
-- __Example:__
--
-- > (users, pagination) <- paginatedSqlQueryWithOptions @User
-- > (users, pagination) <- paginatedSqlQueryWithOptions
-- > (defaultPaginationOptions |> set #maxItems 10)
-- > "SELECT id, firstname, lastname FROM users"
-- > []
-- > ()
--
-- Take a look at "IHP.QueryBuilder" for a typesafe approach on building simple queries.
--
-- *AutoRefresh:* When using 'paginatedSqlQuery' with AutoRefresh, you need to use 'trackTableRead' to let AutoRefresh know that you have accessed a certain table. Otherwise AutoRefresh will not watch table of your custom sql query.
paginatedSqlQueryWithOptions
:: forall model
. ( FromRow model
:: forall r q
. ( FromRow r
, ToRow q
, ?context :: ControllerContext
, ?modelContext :: ModelContext
)
=> Options -> ByteString -> [Action] -> IO ([model], Pagination)
=> Options -> Query -> q -> IO ([r], Pagination)
paginatedSqlQueryWithOptions options sql placeholders = do
count :: Int <- sqlQueryScalar (Query $ "SELECT count(subquery.*) FROM (" <> sql <> ") as subquery") placeholders
count :: Int <- sqlQueryScalar ("SELECT count(subquery.*) FROM (" <> sql <> ") as subquery") placeholders

let pageSize = pageSize' options
pagination = Pagination
Expand All @@ -219,9 +215,9 @@ paginatedSqlQueryWithOptions options sql placeholders = do
, window = windowSize options
}

results :: [model] <- sqlQuery
(Query $ "SELECT subquery.* FROM (" <> sql <> ") as subquery LIMIT ? OFFSET ?")
(placeholders ++ map toField [pageSize, offset' pageSize page])
results :: [r] <- sqlQuery
("SELECT subquery.* FROM (" <> sql <> ") as subquery LIMIT ? OFFSET ?")
(placeholders :. Only pageSize :. Only (offset' pageSize page))

pure (results, pagination)

Expand Down

0 comments on commit cb1ab44

Please sign in to comment.