from sqlalchemy import text
from sqlalchemy.sql import visitors
from . import reflection as _reflection
+from .expression_enum import MatchExpressionModifier
from .enumerated import ENUM
from .enumerated import SET
from .json import JSON
)
def visit_match_op_binary(self, binary, operator, **kw):
- boolean_mode = kw.pop('boolean_mode', True)
+ modifier = kw.pop('modifier', MatchExpressionModifier.in_boolean_mode)
- if boolean_mode:
- template = "MATCH (%s) AGAINST (%s IN BOOLEAN MODE)"
- else:
- template = "MATCH (%s) AGAINST (%s)"
+ match_clause = self.process(binary.left, **kw)
+ against_clause = self.process(binary.right, **kw)
- return template % (
- self.process(binary.left, **kw),
- self.process(binary.right, **kw),
- )
+ if modifier:
+ if not isinstance(modifier, MatchExpressionModifier):
+ raise exc.CompileError(
+ "The `modifier` keyword argument must be a member of "
+ "`sqlalchemy.mysql.expression_enum."
+ "MatchExpressionModifier` enum or `None`"
+ )
+
+ against_clause = ' '.join((
+ against_clause,
+ modifier.value,
+ ))
+
+ return "MATCH (%s) AGAINST (%s)" % (match_clause, against_clause)
def get_from_hint_text(self, table, text):
return text
--- /dev/null
+from ...sql.elements import ClauseElementBatch
+
+
+def match(*clauselist, against, **kwargs):
+ """Produce a ``MATCH (X, Y) AGAINST ('TEXT')`` clause.
+
+ E.g.::
+
+ from sqlalchemy import match
+
+ match_columns_where = match(
+ users_table.c.firstname,
+ users_table.c.lastname,
+ against="John Connor",
+ )
+
+ match_columns_order = match(
+ users_table.c.firstname,
+ users_table.c.lastname,
+ against="John Connor",
+ boolean_mode=False,
+ )
+
+ stmt = select(users_table)\
+ .where(match_columns_where)\
+ .order_by(match_columns_order)
+
+ Would produce SQL resembling::
+
+ SELECT id, firstname, lastname FROM user
+ WHERE MATCH(firstname, lastname)
+ AGAINST (:param_1 IN BOOLEAN MODE)
+ ORDER BY MATCH(firstname, lastname) AGAINST (:param_2)
+
+ The :func:`.match` function is a standalone version of the
+ :meth:`_expression.ColumnElement.match` method available on all
+ SQL expressions, as when :meth:`_expression.ColumnElement.match` is
+ used, but allows to pass multiple columns
+
+ All positional arguments passed to :func:`.match`, should
+ be :class:`_expression.ColumnElement` subclass.
+
+ :param clauselist: a column iterator, typically a
+ :class:`_expression.ColumnElement` instances or alternatively a Python
+ scalar expression to be coerced into a column expression,
+ serving as the ``MATCH`` side of expression.
+
+ :param against: str.
+
+ .. versionadded:: 1.4.4
+
+ .. seealso::
+
+ :meth:`_expression.ColumnElement.match`
+
+ """
+
+ clause_batch = ClauseElementBatch(*clauselist, group=False)
+ return clause_batch.match(against, **kwargs)
--- /dev/null
+import enum
+
+
+class MatchExpressionModifier(enum.Enum):
+ in_natural_language_mode = 'IN NATURAL LANGUAGE MODE'
+
+ in_natural_language_mode_with_query_expansion = \
+ 'IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION'
+
+ in_boolean_mode = 'IN BOOLEAN MODE'
+ with_query_expansion = 'WITH QUERY EXPANSION'
return operators.inv(coercions.expect(roles.ExpressionElementRole, clause))
-def match(*clauselist, against, **kwargs):
- """Produce a ``MATCH (X, Y) AGAINST ('TEXT')`` clause.
-
- E.g.::
-
- from sqlalchemy import match
-
- match_columns_where = match(
- users_table.c.firstname,
- users_table.c.lastname,
- against="John Connor",
- )
-
- match_columns_order = match(
- users_table.c.firstname,
- users_table.c.lastname,
- against="John Connor",
- boolean_mode=False,
- )
-
- stmt = select(users_table)\
- .where(match_columns_where)\
- .order_by(match_columns_order)
-
- Would produce SQL resembling::
-
- SELECT id, firstname, lastname FROM user
- WHERE MATCH(firstname, lastname)
- AGAINST (:param_1 IN BOOLEAN MODE)
- ORDER BY MATCH(firstname, lastname) AGAINST (:param_2)
-
- The :func:`.match` function is a standalone version of the
- :meth:`_expression.ColumnElement.match` method available on all
- SQL expressions, as when :meth:`_expression.ColumnElement.match` is
- used, but allows to pass multiple columns
-
- All positional arguments passed to :func:`.match`, should
- be :class:`_expression.ColumnElement` subclass.
-
- :param clauselist: a column iterator, typically a
- :class:`_expression.ColumnElement` instances or alternatively a Python
- scalar expression to be coerced into a column expression,
- serving as the ``MATCH`` side of expression.
-
- :param against: str.
-
- .. versionadded:: 1.4.4
-
- .. seealso::
-
- :meth:`_expression.ColumnElement.match`
-
- """
-
- clause_batch = ClauseElementBatch(*clauselist, group=False)
- return clause_batch.match(against, **kwargs)
-
-
@inspection._self_inspects
class ClauseElement(
roles.SQLRole,
"lambda_stmt",
"literal",
"literal_column",
- "match",
"not_",
"null",
"nulls_first",
from .elements import Label
from .elements import literal
from .elements import literal_column
-from .elements import match
from .elements import not_
from .elements import Null
from .elements import outparam