Add websearch_to_tsquery support (#1339)
This commit is contained in:
committed by
Steve Chávez
parent
ea97055449
commit
e639c77aa2
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## Unreleased
|
||||
|
||||
- #1243, Add websearch_to_tsquery support - @herulume
|
||||
|
||||
### Added
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -287,7 +287,8 @@ ftsOperators :: M.HashMap Operator SqlFragment
|
||||
ftsOperators = M.fromList [
|
||||
("fts", "@@ to_tsquery"),
|
||||
("plfts", "@@ plainto_tsquery"),
|
||||
("phfts", "@@ phraseto_tsquery")
|
||||
("phfts", "@@ phraseto_tsquery"),
|
||||
("wfts", "@@ websearch_to_tsquery")
|
||||
]
|
||||
|
||||
data OpExpr = OpExpr Bool Operation deriving (Eq, Show)
|
||||
|
||||
@@ -7,12 +7,12 @@ import Test.Hspec
|
||||
import Test.Hspec.Wai
|
||||
import Test.Hspec.Wai.JSON
|
||||
|
||||
import Protolude hiding (get)
|
||||
import PostgREST.Types (PgVersion, pgVersion112)
|
||||
import Protolude hiding (get)
|
||||
import SpecHelper
|
||||
|
||||
|
||||
spec :: SpecWith Application
|
||||
spec =
|
||||
spec :: PgVersion -> SpecWith Application
|
||||
spec actualPgVersion =
|
||||
describe "and/or params used for complex boolean logic" $ do
|
||||
context "used with GET" $ do
|
||||
context "or param" $ do
|
||||
@@ -80,6 +80,19 @@ spec =
|
||||
{"text_search_vector": "'amus':5 'fair':7 'impossibl':9 'peu':4" },
|
||||
{"text_search_vector": "'art':4 'spass':5 'unmog':7"}
|
||||
]|] { matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
when (actualPgVersion >= pgVersion112) $
|
||||
it "can handle wfts (websearch_to_tsquery)" $
|
||||
get "/tsearch?or=(text_search_vector.plfts(german).Art,text_search_vector.plfts(french).amusant,text_search_vector.not.wfts(english).impossible)"
|
||||
`shouldRespondWith`
|
||||
[json|[
|
||||
{"text_search_vector": "'also':2 'fun':3 'possibl':8" },
|
||||
{"text_search_vector": "'ate':3 'cat':2 'fat':1 'rat':4" },
|
||||
{"text_search_vector": "'amus':5 'fair':7 'impossibl':9 'peu':4" },
|
||||
{"text_search_vector": "'art':4 'spass':5 'unmog':7" }
|
||||
]|]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "can handle cs and cd" $
|
||||
get "/entities?or=(arr.cs.{1,2,3},arr.cd.{1})&select=id" `shouldRespondWith`
|
||||
[json|[{ "id": 1 },{ "id": 3 }]|] { matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
@@ -10,11 +10,12 @@ import Test.Hspec.Wai.JSON
|
||||
|
||||
import Text.Heredoc
|
||||
|
||||
import Protolude hiding (get)
|
||||
import PostgREST.Types (PgVersion, pgVersion112)
|
||||
import Protolude hiding (get)
|
||||
import SpecHelper
|
||||
|
||||
spec :: SpecWith Application
|
||||
spec = do
|
||||
spec :: PgVersion -> SpecWith Application
|
||||
spec actualPgVersion = do
|
||||
|
||||
describe "Querying a table with a column called count" $
|
||||
it "should not confuse count column with pg_catalog.count aggregate" $
|
||||
@@ -119,6 +120,29 @@ spec = do
|
||||
[json| [ {"text_search_vector": "'ate':3 'cat':2 'fat':1 'rat':4" }] |]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
when (actualPgVersion >= pgVersion112) $ do
|
||||
it "finds matches with websearch_to_tsquery" $
|
||||
get "/tsearch?text_search_vector=wfts.The%20Fat%20Rats" `shouldRespondWith`
|
||||
[json| [ {"text_search_vector": "'ate':3 'cat':2 'fat':1 'rat':4" }] |]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "can use boolean operators(and, or, -) in websearch_to_tsquery" $ do
|
||||
get "/tsearch?text_search_vector=wfts.fun%20and%20possible"
|
||||
`shouldRespondWith`
|
||||
[json| [ {"text_search_vector": "'also':2 'fun':3 'possibl':8"}] |]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
get "/tsearch?text_search_vector=wfts.impossible%20or%20possible"
|
||||
`shouldRespondWith`
|
||||
[json| [
|
||||
{"text_search_vector": "'fun':5 'imposs':9 'kind':3"},
|
||||
{"text_search_vector": "'also':2 'fun':3 'possibl':8"}]
|
||||
|]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
get "/tsearch?text_search_vector=wfts.fun%20and%20-possible"
|
||||
`shouldRespondWith`
|
||||
[json| [ {"text_search_vector": "'fun':5 'imposs':9 'kind':3"}] |]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "finds matches with different dictionaries" $ do
|
||||
get "/tsearch?text_search_vector=fts(french).amusant" `shouldRespondWith`
|
||||
[json| [{"text_search_vector": "'amus':5 'fair':7 'impossibl':9 'peu':4" }] |]
|
||||
@@ -127,6 +151,12 @@ spec = do
|
||||
[json| [{"text_search_vector": "'amus':5 'fair':7 'impossibl':9 'peu':4" }] |]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
when (actualPgVersion >= pgVersion112) $
|
||||
get "/tsearch?text_search_vector=wfts(french).amusant%20impossible"
|
||||
`shouldRespondWith`
|
||||
[json| [{"text_search_vector": "'amus':5 'fair':7 'impossibl':9 'peu':4" }] |]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "can be negated with not operator" $ do
|
||||
get "/tsearch?text_search_vector=not.fts.impossible%7Cfat%7Cfun" `shouldRespondWith`
|
||||
[json| [
|
||||
@@ -145,6 +175,13 @@ spec = do
|
||||
{"text_search_vector": "'amus':5 'fair':7 'impossibl':9 'peu':4"},
|
||||
{"text_search_vector": "'art':4 'spass':5 'unmog':7"}]|]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
when (actualPgVersion >= pgVersion112) $
|
||||
get "/tsearch?text_search_vector=not.wfts(english).impossible%20or%20fat%20or%20fun"
|
||||
`shouldRespondWith`
|
||||
[json| [
|
||||
{"text_search_vector": "'amus':5 'fair':7 'impossibl':9 'peu':4"},
|
||||
{"text_search_vector": "'art':4 'spass':5 'unmog':7"}]|]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "matches with computed column" $
|
||||
get "/items?always_true=eq.true&order=id.asc" `shouldRespondWith`
|
||||
|
||||
@@ -12,7 +12,8 @@ import Test.Hspec.Wai.JSON
|
||||
import Text.Heredoc
|
||||
|
||||
import PostgREST.Types (PgVersion, pgVersion100, pgVersion109,
|
||||
pgVersion110, pgVersion114, pgVersion95)
|
||||
pgVersion110, pgVersion112, pgVersion114,
|
||||
pgVersion95)
|
||||
import Protolude hiding (get)
|
||||
import SpecHelper
|
||||
|
||||
@@ -531,6 +532,10 @@ spec actualPgVersion =
|
||||
get "/rpc/get_tsearch?text_search_vector=not.fts(english).fun%7Crat" `shouldRespondWith`
|
||||
[json|[{"text_search_vector":"'amus':5 'fair':7 'impossibl':9 'peu':4"},{"text_search_vector":"'art':4 'spass':5 'unmog':7"}]|]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
when (actualPgVersion >= pgVersion112) $
|
||||
get "/rpc/get_tsearch?text_search_vector=wfts.impossible" `shouldRespondWith`
|
||||
[json|[{"text_search_vector":"'fun':5 'imposs':9 'kind':3"}]|]
|
||||
{ matchHeaders = [matchContentTypeJson] }
|
||||
|
||||
it "should work with an argument of custom type in public schema" $
|
||||
get "/rpc/test_arg?my_arg=something" `shouldRespondWith`
|
||||
|
||||
+2
-2
@@ -91,12 +91,12 @@ main = do
|
||||
, ("Feature.DeleteSpec" , Feature.DeleteSpec.spec)
|
||||
, ("Feature.InsertSpec" , Feature.InsertSpec.spec actualPgVersion)
|
||||
, ("Feature.JsonOperatorSpec" , Feature.JsonOperatorSpec.spec actualPgVersion)
|
||||
, ("Feature.QuerySpec" , Feature.QuerySpec.spec)
|
||||
, ("Feature.QuerySpec" , Feature.QuerySpec.spec actualPgVersion)
|
||||
, ("Feature.RpcSpec" , Feature.RpcSpec.spec actualPgVersion)
|
||||
, ("Feature.RangeSpec" , Feature.RangeSpec.spec)
|
||||
, ("Feature.SingularSpec" , Feature.SingularSpec.spec)
|
||||
, ("Feature.StructureSpec" , Feature.StructureSpec.spec)
|
||||
, ("Feature.AndOrParamsSpec" , Feature.AndOrParamsSpec.spec)
|
||||
, ("Feature.AndOrParamsSpec" , Feature.AndOrParamsSpec.spec actualPgVersion)
|
||||
] ++ extraSpecs
|
||||
|
||||
hspec $ do
|
||||
|
||||
Reference in New Issue
Block a user