| 225 | |
| 226 | |
| 227 | class SearchQuery(SearchQueryCombinable, Func): |
| 228 | output_field = SearchQueryField() |
| 229 | SEARCH_TYPES = { |
| 230 | "plain": "plainto_tsquery", |
| 231 | "phrase": "phraseto_tsquery", |
| 232 | "raw": "to_tsquery", |
| 233 | "websearch": "websearch_to_tsquery", |
| 234 | } |
| 235 | |
| 236 | def __init__( |
| 237 | self, |
| 238 | value, |
| 239 | output_field=None, |
| 240 | *, |
| 241 | config=None, |
| 242 | invert=False, |
| 243 | search_type="plain", |
| 244 | ): |
| 245 | if isinstance(value, LexemeCombinable): |
| 246 | search_type = "raw" |
| 247 | |
| 248 | self.function = self.SEARCH_TYPES.get(search_type) |
| 249 | if self.function is None: |
| 250 | raise ValueError("Unknown search_type argument '%s'." % search_type) |
| 251 | if not hasattr(value, "resolve_expression"): |
| 252 | value = Value(value) |
| 253 | expressions = (value,) |
| 254 | self.config = SearchConfig.from_parameter(config) |
| 255 | if self.config is not None: |
| 256 | expressions = [self.config, *expressions] |
| 257 | self.invert = invert |
| 258 | super().__init__(*expressions, output_field=output_field) |
| 259 | |
| 260 | def as_sql(self, compiler, connection, function=None, template=None): |
| 261 | sql, params = super().as_sql(compiler, connection, function, template) |
| 262 | if self.invert: |
| 263 | sql = "!!(%s)" % sql |
| 264 | return sql, params |
| 265 | |
| 266 | def __invert__(self): |
| 267 | clone = self.copy() |
| 268 | clone.invert = not self.invert |
| 269 | return clone |
| 270 | |
| 271 | def __str__(self): |
| 272 | result = super().__str__() |
| 273 | return ("~%s" % result) if self.invert else result |
| 274 | |
| 275 | |
| 276 | class CombinedSearchQuery(SearchQueryCombinable, CombinedExpression): |