6
6
{-# LANGUAGE QuasiQuotes #-}
7
7
{-# LANGUAGE RankNTypes #-}
8
8
{-# LANGUAGE FlexibleContexts #-}
9
+ {-# LANGUAGE FlexibleInstances #-}
9
10
{-# LANGUAGE TypeFamilies #-}
10
11
{-# LANGUAGE GADTs #-}
11
12
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
13
+ {-# LANGUAGE ScopedTypeVariables #-}
12
14
module Database.Esqueleto.TextSearchSpec (main , spec ) where
13
15
14
16
import Control.Monad (forM_ )
@@ -19,15 +21,17 @@ import Control.Monad.Logger (MonadLogger(..), runStderrLoggingT)
19
21
import Control.Monad.Trans.Resource (
20
22
MonadBaseControl , MonadThrow , ResourceT , runResourceT )
21
23
import Database.Esqueleto (
22
- SqlExpr , Value (.. ), update , select , set , val , from , where_ , (=.) , (^.) )
23
- import Database.Persist (entityKey , insert , get )
24
+ SqlExpr , Value (.. ), unValue , update , select , set , val , from , where_
25
+ , (=.) , (^.) )
26
+ import Database.Persist (entityKey , insert , get , PersistField (.. ))
24
27
import Database.Persist.Postgresql (
25
28
SqlPersistT , ConnectionString , runSqlConn , transactionUndo
26
29
, withPostgresqlConn , runMigration )
27
30
import Database.Persist.TH (
28
31
mkPersist , mkMigrate , persistUpperCase , share , sqlSettings )
29
32
import Test.Hspec (Spec , hspec , describe , it , shouldBe )
30
- import Test.QuickCheck (Arbitrary (.. ), property , oneof , listOf , listOf1 , choose )
33
+ import Test.QuickCheck (
34
+ Arbitrary (.. ), property , elements , oneof , listOf , listOf1 , choose )
31
35
32
36
import Database.Esqueleto.TextSearch
33
37
@@ -152,25 +156,29 @@ spec = do
152
156
textToQuery " 'foo'" `shouldBe` Right (lexm " foo" )
153
157
it " can parse it surrounded by spaces" $
154
158
textToQuery " 'foo' " `shouldBe` Right (lexm " foo" )
159
+
155
160
describe " infix lexeme with weights" $ do
156
161
it " can parse it" $
157
162
textToQuery " 'foo':AB"
158
163
`shouldBe` Right (Lexeme Infix [Highest ,High ] " foo" )
159
164
it " can parse it surrounded by spaces" $
160
165
textToQuery " 'foo':AB "
161
166
`shouldBe` Right (Lexeme Infix [Highest ,High ] " foo" )
167
+
162
168
describe " prefix lexeme" $ do
163
169
it " can parse it" $
164
170
textToQuery " 'foo':*" `shouldBe` Right (Lexeme Prefix [] " foo" )
165
171
it " can parse it surrounded byb spaces" $
166
172
textToQuery " 'foo':* " `shouldBe` Right (Lexeme Prefix [] " foo" )
173
+
167
174
describe " prefix lexeme with weights" $ do
168
175
it " can parse it" $
169
176
textToQuery " 'foo':*AB" `shouldBe`
170
177
Right (Lexeme Prefix [Highest ,High ] " foo" )
171
178
it " can parse it surrounded by spaces" $
172
179
textToQuery " 'foo':*AB " `shouldBe`
173
180
Right (Lexeme Prefix [Highest ,High ] " foo" )
181
+
174
182
describe " &" $ do
175
183
it " can parse it" $
176
184
textToQuery " 'foo'&'bar'" `shouldBe`
@@ -187,21 +195,25 @@ spec = do
187
195
it " can parse several" $
188
196
textToQuery " 'foo'&'bar'&'car'" `shouldBe`
189
197
Right (lexm " foo" :& lexm " bar" :& lexm " car" )
198
+
190
199
describe " |" $ do
191
200
it " can parse it" $
192
201
textToQuery " 'foo'|'bar'" `shouldBe` Right (lexm " foo" :| lexm " bar" )
193
202
it " can parse several" $
194
203
textToQuery " 'foo'|'bar'|'car'" `shouldBe`
195
204
Right (lexm " foo" :| lexm " bar" :| lexm " car" )
205
+
196
206
describe " mixed |s and &s" $ do
197
207
it " respects precedence" $ do
198
208
textToQuery " 'foo'|'bar'&'car'" `shouldBe`
199
209
Right (lexm " foo" :| lexm " bar" :& lexm " car" )
200
210
textToQuery " 'foo'&'bar'|'car'" `shouldBe`
201
211
Right (lexm " foo" :& lexm " bar" :| lexm " car" )
212
+
202
213
describe " !" $ do
203
214
it " can parse it" $
204
215
textToQuery " !'foo'" `shouldBe` Right (Not (lexm " foo" ))
216
+
205
217
describe " ! and &" $ do
206
218
it " can parse it" $ do
207
219
textToQuery " !'foo'&'car'" `shouldBe`
@@ -237,6 +249,39 @@ spec = do
237
249
return a
238
250
liftIO $ length result2 `shouldBe` 0
239
251
252
+ describe " ts_rank_cd" $ do
253
+ it " works as expected" $ run $ do
254
+ let vector = to_tsvector (val " english" ) (val content)
255
+ content = " content" :: Text
256
+ query = to_tsquery (val " english" ) (val " content" )
257
+ norm = val []
258
+ ret <- select $ return $ ts_rank_cd (val def) vector query norm
259
+ liftIO $ map unValue ret `shouldBe` [0.1 ]
260
+
261
+ describe " ts_rank" $ do
262
+ it " works as expected" $ run $ do
263
+ let vector = to_tsvector (val " english" ) (val content)
264
+ content = " content" :: Text
265
+ query = to_tsquery (val " english" ) (val " content" )
266
+ norm = val []
267
+ ret <- select $ return $ ts_rank (val def) vector query norm
268
+ liftIO $ map unValue ret `shouldBe` [6.07927e-2 ]
269
+
270
+ describe " NormalizationOption" $ do
271
+ describe " fromPersistValue . toPersistValue" $ do
272
+ let isEqual [] [] = True
273
+ isEqual [NormNone ] [] = True
274
+ isEqual [] [NormNone ] = True
275
+ isEqual a b = a == b
276
+ toRight (Right a) = a
277
+ toRight _ = error " unexpected Left"
278
+ it " is isomorphism" $ property $ \ (q :: [NormalizationOption ]) ->
279
+ isEqual ((toRight . fromPersistValue . toPersistValue) q) q
280
+ `shouldBe` True
281
+
282
+ instance Arbitrary ([NormalizationOption ]) where
283
+ arbitrary = (: [] ) <$> elements [minBound .. maxBound ]
284
+
240
285
instance a ~ Lexemes => Arbitrary (TsQuery a ) where
241
286
arbitrary = query 0
242
287
where
0 commit comments