packages feed

opaleye-textsearch-0.1.0.0: src/Opaleye/TextSearch.hs

{-# OPTIONS_HADDOCK show-extensions #-}

{-|
Module      : Opaleye.TextSearch
Description : PostgreSQL Full Text Search support for opaleye
Copyright   : (c) Gargantext 2024-
License     : AGPL-3.0-or-later
Maintainer  : gargantext@iscpif.fr
Stability   : 0.1.0.0
Portability : POSIX
                                                               -}
module Opaleye.TextSearch (
  -- * How to use
  -- $use
    
  -- * Types
    SqlTSQuery
  , SqlTSVector

  -- * Functions and operators
  , (@@)
  , pgTSVector
  , pgTSQuery
  , sqlTSQuery
  
  -- * Various parsing queries
  -- $parsing_queries
  , sqlPlainToTSQuery
  , sqlToTSQuery

  -- * Internals (mostly)
  , to_pgTSQuery
  , plainto_pgTSQuery
  ) where

import           Opaleye.Internal.Column (Field)
import           Opaleye.Internal.PGTypesExternal (SqlText)
import           Opaleye.SqlTypes (sqlString)
import           Opaleye.TextSearch.Internal.Types
import           Opaleye.TextSearch.Operators ((@@))
import qualified Opaleye.Internal.Column as C
import qualified Opaleye.Internal.HaskellDB.PrimQuery as HPQ
import GHC.RTS.Flags (TraceFlags(user))

{- $use

__Example__:
    
@
data MyEntity id text search =
  MyEntity { _id      :: id
           , _text    :: text
           , _search  :: search }
  deriving ('Show', 'GHC.Generics.Generic')

$('Data.Profunctor.Product.TH.makeAdaptorAndInstance' \"pMyEntity\" ''MyEntity)

type MyEntityRead =
  MyEntity
    ('Field' 'SqlInt4'     )
    ('Field' 'SqlText'     )
    ('Field' 'SqlTSVector' )

type MyEntityWrite =
  MyEntity
    ('Maybe' ('Field' 'SqlInt4' ))
    ('Field' 'SqlText'          )
    ('Field' 'SqlTSVector'      )

myEntityTable :: 'Opaleye.Internal.Table' MyEntityWrite MyEntityRead
myEntityTable = 'Opaleye.Internal.Table' \"my_entity\" ( pMyEntity
                                   MyEntity { _id           = 'Opaleye.Internal.Table.optionalTableField' \"id\"
                                            , _text         = 'Opaleye.Internal.Table.requiredTableField' \"text\"
                                            , _search       = 'Opaleye.Internal.Table.optionalTableField' \"search_vector\"
                                            }
                                   )

myQuery :: 'Text' -> 'Opaleye.Internal.Sql.Select' ('Opaleye.Internal.Column.Column' 'SqlInt4', 'Opaleye.Internal.Column' 'SqlText')
myQuery q = proc () -> do
    row <- myEntityTable -< ()
    'Opaleye.Operators.restrict' -< (_search row)    @@ ('sqlPlainToTSQuery' (unpack q))
    'Control.Arrow.returnA'  -< (_id row, _text row)
	
	
'Opaleye.runSelect' conn (myQuery \"hello world\")
@

-}
    
-- Full Text Search

-- | PostgreSQL @tsvector@ coercion from text.
pgTSVector :: Field SqlText -> Field SqlTSVector
pgTSVector (C.Column e) = C.Column (HPQ.FunExpr "tsvector" [e])

-- | PostgreSQL @tsquery@ coercion from text.
pgTSQuery :: Field SqlText -> Field SqlTSQuery
pgTSQuery (C.Column e) = C.Column (HPQ.FunExpr "tsquery" [e])

-- | Coerce given 'String' to @tsquery@.
sqlTSQuery :: String -> Field SqlTSQuery
sqlTSQuery = pgTSQuery . sqlString

{- $parsing_queries
For @to_tsquery@, @plainto_tsquery@, etc. functions, see "Parsing
queries" section in [PostgreSQL
docs](https://www.postgresql.org/docs/16/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES)
-}

-- | Call 'plainto_tsquery'.
sqlPlainToTSQuery :: String -> Field SqlTSQuery
sqlPlainToTSQuery = plainto_pgTSQuery
    
-- | Call @to_tsquery@ on the input string.
sqlToTSQuery :: String -> Field SqlTSQuery
sqlToTSQuery = to_pgTSQuery

-- | Converts a 'String' into a Postgres' tsQuery by calling @to_tsquery@ on the input string.
to_pgTSQuery :: String -> Field SqlTSQuery
to_pgTSQuery query = C.Column (HPQ.FunExpr "to_tsquery" [HPQ.ConstExpr (HPQ.StringLit query)])

-- | Converts a 'String' into a Postgres' tsQuery by calling @plainto_tsquery@ on the input string.
plainto_pgTSQuery :: String -> Field SqlTSQuery
plainto_pgTSQuery query = C.Column (HPQ.FunExpr "plainto_tsquery" [HPQ.ConstExpr (HPQ.StringLit query)])