]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Move dialect-specific code to it's directory + implement against modifier
authorAnton Kovalevich <kai3341@gmail.com>
Fri, 26 Mar 2021 01:46:35 +0000 (04:46 +0300)
committerAnton Kovalevich <kai3341@gmail.com>
Fri, 26 Mar 2021 01:46:35 +0000 (04:46 +0300)
lib/sqlalchemy/dialects/mysql/base.py
lib/sqlalchemy/dialects/mysql/expression.py [new file with mode: 0644]
lib/sqlalchemy/dialects/mysql/expression_enum.py [new file with mode: 0644]
lib/sqlalchemy/sql/elements.py
lib/sqlalchemy/sql/expression.py

index 79104155320df8a75442aee6bebc267f0390876d..8eb2250ac7387fb70093b2149807e34f5f409eff 100644 (file)
@@ -934,6 +934,7 @@ from sqlalchemy import literal_column
 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
@@ -1588,17 +1589,25 @@ class MySQLCompiler(compiler.SQLCompiler):
         )
 
     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
diff --git a/lib/sqlalchemy/dialects/mysql/expression.py b/lib/sqlalchemy/dialects/mysql/expression.py
new file mode 100644 (file)
index 0000000..c8da185
--- /dev/null
@@ -0,0 +1,59 @@
+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)
diff --git a/lib/sqlalchemy/dialects/mysql/expression_enum.py b/lib/sqlalchemy/dialects/mysql/expression_enum.py
new file mode 100644 (file)
index 0000000..1548dba
--- /dev/null
@@ -0,0 +1,11 @@
+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'
index 1f77d015807b5d330a0d1fcb31a0d935790fda64..0c6fc51c275639574085ecfa059e6e343c7fba41 100644 (file)
@@ -177,64 +177,6 @@ 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,
index 2861da2efc9f102371c72a22f7fa135d0e2ae9b8..f47dc5fdf0c88052c9576d9a8570f788cb263c09 100644 (file)
@@ -66,7 +66,6 @@ __all__ = [
     "lambda_stmt",
     "literal",
     "literal_column",
-    "match",
     "not_",
     "null",
     "nulls_first",
@@ -123,7 +122,6 @@ from .elements import Grouping
 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