]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Implement an `sqlalchemy.sql.expression.match` expression
authorAnton Kovalevich <kai3341@gmail.com>
Thu, 25 Mar 2021 12:08:48 +0000 (15:08 +0300)
committerAnton Kovalevich <kai3341@gmail.com>
Thu, 25 Mar 2021 12:08:48 +0000 (15:08 +0300)
lib/sqlalchemy/dialects/mysql/base.py
lib/sqlalchemy/sql/elements.py

index e6052f69f7e81be06d7cac8883aa57fa51cebdea..79104155320df8a75442aee6bebc267f0390876d 100644 (file)
@@ -1588,7 +1588,14 @@ class MySQLCompiler(compiler.SQLCompiler):
         )
 
     def visit_match_op_binary(self, binary, operator, **kw):
-        return "MATCH (%s) AGAINST (%s IN BOOLEAN MODE)" % (
+        boolean_mode = kw.pop('boolean_mode', True)
+
+        if boolean_mode:
+            template = "MATCH (%s) AGAINST (%s IN BOOLEAN MODE)"
+        else:
+            template = "MATCH (%s) AGAINST (%s)"
+
+        return template % (
             self.process(binary.left, **kw),
             self.process(binary.right, **kw),
         )
index 20c3e899114467b2f2054ad207b14d5612331f55..1f77d015807b5d330a0d1fcb31a0d935790fda64 100644 (file)
@@ -177,6 +177,64 @@ def not_(clause):
     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,
@@ -2226,6 +2284,15 @@ class ClauseList(
             return self
 
 
+class ClauseElementBatch(ClauseList, ColumnElement):
+    """Describe a batch of clauses, separated by an operator, but processing
+    as single column.
+
+    By default, is comma-separated, such as a column listing.
+
+    """
+
+
 class BooleanClauseList(ClauseList, ColumnElement):
     __visit_name__ = "clauselist"
     inherit_cache = True