Skip to content

Remove connLimitOffset #1325

@parsonsmatt

Description

@parsonsmatt

connLimitOffset is used in esqueleto, which has me investigating it.

These are the uses of the term in persistent repository:

λ ~/Projects/persistent/ master rg connLimitOffset
persistent-sqlite/Database/Persist/Sqlite.hs
291:            , connLimitOffset = decorateSQLWithLimitOffset "LIMIT -1"
482:                , connLimitOffset = decorateSQLWithLimitOffset "LIMIT -1"

persistent/ChangeLog.md
95:    * The `connLimitOffset` function used to have a `Bool` parameter. This

persistent-postgresql/Database/Persist/Postgresql.hs
407:        , connLimitOffset = decorateSQLWithLimitOffset "LIMIT ALL"
1778:                , connLimitOffset = undefined

persistent/Database/Persist/SqlBackend.hs
119:    func <- asks (SqlBackend.connLimitOffset . projectBackend)

persistent/Database/Persist/SqlBackend/Internal.hs
112:    , connLimitOffset :: (Int,Int) -> Text -> Text

persistent/Database/Persist/Sql/Orphan/PersistQuery.hs
119:        sql conn = connLimitOffset conn (limit,offset) $ mconcat
140:        sql conn = connLimitOffset conn (limit,offset) $ mconcat

persistent/Database/Persist/SqlBackend/Internal/MkSqlBackend.hs
71:    , connLimitOffset :: (Int,Int) -> Text -> Text

persistent-mysql/Database/Persist/MySQL.hs
155:                , connLimitOffset = decorateSQLWithLimitOffset "LIMIT 18446744073709551615"
1303:                , connLimitOffset = undefined

In other words, it is always assigned with the result of decorateSqlWithLimitOffset applied to that Text parameter.

λ ~/Projects/persistent/ master rg decorateSQLWithLimitOffset
persistent-sqlite/Database/Persist/Sqlite.hs
291:            , connLimitOffset = decorateSQLWithLimitOffset "LIMIT -1"
482:                , connLimitOffset = decorateSQLWithLimitOffset "LIMIT -1"

persistent-postgresql/Database/Persist/Postgresql.hs
407:        , connLimitOffset = decorateSQLWithLimitOffset "LIMIT ALL"

persistent/Database/Persist/Sql.hs
57:    , decorateSQLWithLimitOffset

persistent/Database/Persist/Sql/Orphan/PersistQuery.hs
14:    , decorateSQLWithLimitOffset
485:decorateSQLWithLimitOffset
490:decorateSQLWithLimitOffset nolimit (limit,offset) sql =

persistent-mysql/Database/Persist/MySQL.hs
155:                , connLimitOffset = decorateSQLWithLimitOffset "LIMIT 18446744073709551615"

That is implemented in Database.Persist.Sql.Orphan.PersistQuery here:

-- | Generates sql for limit and offset for postgres, sqlite and mysql.
decorateSQLWithLimitOffset
    :: Text
    -> (Int,Int)
    -> Text
    -> Text
decorateSQLWithLimitOffset nolimit (limit,offset) sql =
    let
        lim = case (limit, offset) of
                (0, 0) -> ""
                (0, _) -> T.cons ' ' nolimit
                (_, _) -> " LIMIT " <> T.pack (show limit)
        off = if offset == 0
                    then ""
                    else " OFFSET " <> T.pack (show offset)
    in mconcat
            [ sql
            , lim
            , off
            ]

noLimit is necessary because MySQL and Sqlite throw a syntax error if you have an OFFSET without a corresponding LIMIT clause.

Since the noLimit parameter is actually what varies, let's store that in the record instead of the function. Then, decorating with LIMIT/OFFSET can be done as a function implemented directly.

This simplifies esqueleto's use-case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions