orville-postgresql-1.1.0.0: src/Orville/PostgreSQL/Expr/TextSearch.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{- |
Copyright : Flipstone Technology Partners 2024-2025
License : MIT
Stability : Stable
@since 1.1.0.0
-}
module Orville.PostgreSQL.Expr.TextSearch
( TSVector
, tsVectorToValueExpression
, TSQuery
, tsQueryToValueExpression
, TSWeight
, tsMatch
, tsMatchTSQueryTSVector
, tsVectorConcat
, toTSVector
, toTSQuery
, plainToTSQuery
, toTSRank
, setTSWeight
, tsWeightToValueExpression
, tsWeightA
, tsWeightB
, tsWeightC
, tsWeightD
, RegConfig
, arabicRegConfig
, danishRegConfig
, dutchRegConfig
, englishRegConfig
, finnishRegConfig
, frenchRegConfig
, germanRegConfig
, greekRegConfig
, hungarianRegConfig
, indonesianRegConfig
, irishRegConfig
, italianRegConfig
, lithuanianRegConfig
, nepaliRegConfig
, norwegianRegConfig
, portugueseRegConfig
, romanianRegConfig
, russianRegConfig
, simpleRegConfig
, spanishRegConfig
, swedishRegConfig
, tamilRegConfig
, turkishRegConfig
) where
import Orville.PostgreSQL.Expr.BinaryOperator (BinaryOperator, binaryOpExpression, binaryOperator)
import Orville.PostgreSQL.Expr.Name (FunctionName, functionName)
import Orville.PostgreSQL.Expr.ValueExpression (ValueExpression, functionCall)
import Orville.PostgreSQL.Expr.WhereClause (BooleanExpr)
import qualified Orville.PostgreSQL.Raw.RawSql as RawSql
{- | Type to represent a PostgreSQL @tsvector@.
'TSVector' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom
SQL.
@since 1.1.0.0
-}
newtype TSVector
= TSVector RawSql.RawSql
deriving
( -- | @since 1.1.0.0
RawSql.SqlExpression
)
{- | Type to represent a PostgreSQL @tsquery@.
'TSQuery' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom
SQL.
@since 1.1.0.0
-}
newtype TSQuery
= TSQuery RawSql.RawSql
deriving
( -- | @since 1.1.0.0
RawSql.SqlExpression
)
{- | A type to represent the weight to be given to elements of a 'TSVector'
'TSWeight' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom SQL.
@since 1.1.0.0
-}
newtype TSWeight
= TSWeight RawSql.RawSql
deriving
( -- | @since 1.1.0.0
RawSql.SqlExpression
)
tsMatchOp :: BinaryOperator
tsMatchOp = binaryOperator "@@"
tsVectorConcatOp :: BinaryOperator
tsVectorConcatOp = binaryOperator "||"
{- | Matches a 'TSVector' against a 'TSQuery'. This function is an alias for the '@@' operator.
@since 1.1.0.0
-}
tsMatch :: TSVector -> TSQuery -> BooleanExpr
tsMatch tsVector tsQuery =
binaryOpExpression
tsMatchOp
(tsVectorToValueExpression tsVector)
(tsQueryToValueExpression tsQuery)
{- | Matches a 'TSQuery' against a 'TSVector'. This function is an alias for the '@@' operator.
Filped version of 'tsMatch'
@since 1.1.0.0
-}
tsMatchTSQueryTSVector :: TSQuery -> TSVector -> BooleanExpr
tsMatchTSQueryTSVector = flip tsMatch
{- | Concatenates two 'TSVector' values.
@since 1.1.0.0
-}
tsVectorConcat :: TSVector -> TSVector -> TSVector
tsVectorConcat tsVector1 tsVector2 =
binaryOpExpression
tsVectorConcatOp
(tsVectorToValueExpression tsVector1)
(tsVectorToValueExpression tsVector2)
{- | A constant representing the "A" weight for a 'TSVector'.
@since 1.1.0.0
-}
tsWeightA :: TSWeight
tsWeightA = TSWeight $ RawSql.fromString "\'A\'"
{- | A constant representing the "B" weight for a 'TSVector'.
@since 1.1.0.0
-}
tsWeightB :: TSWeight
tsWeightB = TSWeight $ RawSql.fromString "\'B\'"
{- | A constant representing the "C" weight for a 'TSVector'.
@since 1.1.0.0
-}
tsWeightC :: TSWeight
tsWeightC = TSWeight $ RawSql.fromString "\'C\'"
{- | A constant representing the "D" weight for a 'TSVector'.
@since 1.1.0.0
-}
tsWeightD :: TSWeight
tsWeightD = TSWeight $ RawSql.fromString "\'D\'"
toTSVectorFunction :: FunctionName
toTSVectorFunction = functionName "to_tsvector"
toTSQueryFunction :: FunctionName
toTSQueryFunction = functionName "to_tsquery"
toTSRankFunction :: FunctionName
toTSRankFunction = functionName "ts_rank"
setTSWeightFunction :: FunctionName
setTSWeightFunction = functionName "setweight"
plaintoTSQueryFunction :: FunctionName
plaintoTSQueryFunction = functionName "plainto_tsquery"
{- | Converts a 'RegConfig' to a 'ValueExpression'.
@since 1.1.0.0
-}
regConfigToValueExpression :: RegConfig -> ValueExpression
regConfigToValueExpression (RegConfig regConfig) =
RawSql.unsafeFromRawSql
( RawSql.fromString "\'"
<> regConfig
<> RawSql.fromString "\'"
)
{- | Converts a 'ValueExpression' to a 'TSVector', optionally using a specified 'RegConfig'.
The provided 'ValueExpression' must adhere to the following limitations:
* It must evaluate to one of the following types: @text@, @json@, or @jsonb@.
* Behavior may differ depending on whether @json@ or @jsonb@ is used.
* Word normalization will be applied during the conversion process.
@since 1.1.0.0
-}
toTSVector :: ValueExpression -> Maybe RegConfig -> TSVector
toTSVector val mbRegConfig =
TSVector
. RawSql.toRawSql
. functionCall toTSVectorFunction
$ case mbRegConfig of
Nothing -> [val]
Just regConfig -> [regConfigToValueExpression regConfig, val]
{- | Converts a 'ValueExpression' to a 'TSQuery', optionally using a specified 'RegConfig'.
The provided 'ValueExpression' must adhere to the following limitations:
* It must evaluate to one of the following types: @text@, @json@, or @jsonb@.
* Behavior may differ depending on whether @json@ or @jsonb@ is used.
* Word normalization will be applied during the conversion process.
@since 1.1.0.0
-}
toTSQuery :: ValueExpression -> Maybe RegConfig -> TSQuery
toTSQuery val mbRegConfig =
TSQuery
. RawSql.toRawSql
. functionCall toTSQueryFunction
$ case mbRegConfig of
Nothing -> [val]
Just regConfig -> [regConfigToValueExpression regConfig, val]
{- | Converts a 'TSQuery' to a 'ValueExpression'.
@since 1.1.0.0
-}
tsQueryToValueExpression :: TSQuery -> ValueExpression
tsQueryToValueExpression (TSQuery rawSql) = RawSql.unsafeFromRawSql rawSql
{- | Converts a 'TSVector' to a 'ValueExpression'.
@since 1.1.0.0
-}
tsVectorToValueExpression :: TSVector -> ValueExpression
tsVectorToValueExpression (TSVector rawSql) = RawSql.unsafeFromRawSql rawSql
{- | Perform a text search ranking based on how well the 'TSVector' and 'TSQuery' match.
@since 1.1.0.0
-}
toTSRank :: TSVector -> TSQuery -> ValueExpression
toTSRank tsVector tsQuery =
functionCall
toTSRankFunction
[ tsVectorToValueExpression tsVector
, tsQueryToValueExpression tsQuery
]
{- | Assigns the given weight to each element of a 'TSVector'.
@since 1.1.0.0
-}
setTSWeight :: TSVector -> TSWeight -> TSVector
setTSWeight tsVector tsWeight =
TSVector . RawSql.toRawSql $
functionCall
setTSWeightFunction
[tsVectorToValueExpression tsVector, tsWeightToValueExpression tsWeight]
{- | Converts a 'TSWeight' to a 'ValueExpression'.
@since 1.1.0.0
-}
tsWeightToValueExpression :: TSWeight -> ValueExpression
tsWeightToValueExpression (TSWeight rawSql) = RawSql.unsafeFromRawSql rawSql
{- | Converts a 'ValueExpression' into a 'TSQuery', optionally using a specified 'RegConfig'. The
'ValueExpression' must be text. All punctuation in the given 'ValueExpression' will be ignored
and individual words will be combined with a logical AND. This results in a 'TSQuery' that
matches when all words are present.
@since 1.1.0.0
-}
plainToTSQuery :: ValueExpression -> Maybe RegConfig -> TSQuery
plainToTSQuery val mbRegConfig =
TSQuery
. RawSql.toRawSql
. functionCall plaintoTSQueryFunction
$ case mbRegConfig of
Nothing -> [val]
Just regConfig -> [regConfigToValueExpression regConfig, val]
{- | Type to represent a text search configuration.
'RegConfig' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom
SQL.
@since 1.1.0.0
-}
newtype RegConfig
= RegConfig RawSql.RawSql
deriving
( -- | @since 1.1.0.0
RawSql.SqlExpression
)
{- | The "arabic" text search configuration.
@since 1.1.0.0
-}
arabicRegConfig :: RegConfig
arabicRegConfig = RegConfig $ RawSql.fromString "arabic"
{- | The "danish" text search configuration.
@since 1.1.0.0
-}
danishRegConfig :: RegConfig
danishRegConfig = RegConfig $ RawSql.fromString "danish"
{- | The "dutch" text search configuration.
@since 1.1.0.0
-}
dutchRegConfig :: RegConfig
dutchRegConfig = RegConfig $ RawSql.fromString "dutch"
{- | The "english" text search configuration.
@since 1.1.0.0
-}
englishRegConfig :: RegConfig
englishRegConfig = RegConfig $ RawSql.fromString "english"
{- | The "finnish" text search configuration.
@since 1.1.0.0
-}
finnishRegConfig :: RegConfig
finnishRegConfig = RegConfig $ RawSql.fromString "finnish"
{- | The "french" text search configuration.
@since 1.1.0.0
-}
frenchRegConfig :: RegConfig
frenchRegConfig = RegConfig $ RawSql.fromString "french"
{- | The "german" text search configuration.
@since 1.1.0.0
-}
germanRegConfig :: RegConfig
germanRegConfig = RegConfig $ RawSql.fromString "german"
{- | The "greek" text search configuration.
@since 1.1.0.0
-}
greekRegConfig :: RegConfig
greekRegConfig = RegConfig $ RawSql.fromString "greek"
{- | The "hungarian" text search configuration.
@since 1.1.0.0
-}
hungarianRegConfig :: RegConfig
hungarianRegConfig = RegConfig $ RawSql.fromString "hungarian"
{- | The "indonesian" text search configuration.
@since 1.1.0.0
-}
indonesianRegConfig :: RegConfig
indonesianRegConfig = RegConfig $ RawSql.fromString "indonesian"
{- | The "irish" text search configuration.
@since 1.1.0.0
-}
irishRegConfig :: RegConfig
irishRegConfig = RegConfig $ RawSql.fromString "irish"
{- | The "italian" text search configuration.
@since 1.1.0.0
-}
italianRegConfig :: RegConfig
italianRegConfig = RegConfig $ RawSql.fromString "italian"
{- | The "lithuanian" text search configuration.
@since 1.1.0.0
-}
lithuanianRegConfig :: RegConfig
lithuanianRegConfig = RegConfig $ RawSql.fromString "lithuanian"
{- | The "nepali" text search configuration.
@since 1.1.0.0
-}
nepaliRegConfig :: RegConfig
nepaliRegConfig = RegConfig $ RawSql.fromString "nepali"
{- | The "norwegian" text search configuration.
@since 1.1.0.0
-}
norwegianRegConfig :: RegConfig
norwegianRegConfig = RegConfig $ RawSql.fromString "norwegian"
{- | The "portuguese" text search configuration.
@since 1.1.0.0
-}
portugueseRegConfig :: RegConfig
portugueseRegConfig = RegConfig $ RawSql.fromString "portuguese"
{- | The "romanian" text search configuration.
@since 1.1.0.0
-}
romanianRegConfig :: RegConfig
romanianRegConfig = RegConfig $ RawSql.fromString "romanian"
{- | The "russian" text search configuration.
@since 1.1.0.0
-}
russianRegConfig :: RegConfig
russianRegConfig = RegConfig $ RawSql.fromString "russian"
{- | The "simple" text search configuration.
@since 1.1.0.0
-}
simpleRegConfig :: RegConfig
simpleRegConfig = RegConfig $ RawSql.fromString "simple"
{- | The "spanish" text search configuration.
@since 1.1.0.0
-}
spanishRegConfig :: RegConfig
spanishRegConfig = RegConfig $ RawSql.fromString "spanish"
{- | The "swedish" text search configuration.
@since 1.1.0.0
-}
swedishRegConfig :: RegConfig
swedishRegConfig = RegConfig $ RawSql.fromString "swedish"
{- | The "tamil" text search configuration.
@since 1.1.0.0
-}
tamilRegConfig :: RegConfig
tamilRegConfig = RegConfig $ RawSql.fromString "tamil"
{- | The "turkish" text search configuration.
@since 1.1.0.0
-}
turkishRegConfig :: RegConfig
turkishRegConfig = RegConfig $ RawSql.fromString "turkish"