Repository navigation
Apache Doris Full Text Search Operators has sqlglot.errors.ParseError: Invalid expression / Unexpected token #36770
Description
Bug description
superset_app | 2025-12-19 19:40:41,270:INFO:superset.commands.sql_lab.execute:Triggering query_id: 78
superset_app | 2025-12-19 19:40:41,276:WARNING:superset.views.error_handling:SupersetErrorException
superset_app | Traceback (most recent call last):
superset_app | File "/app/superset/sql/parse.py", line 562, in _parse
superset_app | statements = sqlglot.parse(script, dialect=dialect)
superset_app | File "/app/.venv/lib/python3.10/site-packages/sqlglot/init.py", line 102, in parse
superset_app | return Dialect.get_or_raise(read or dialect).parse(sql, **opts)
superset_app | File "/app/.venv/lib/python3.10/site-packages/sqlglot/dialects/dialect.py", line 1083, in parse
superset_app | return self.parser(**opts).parse(self.tokenize(sql), sql)
superset_app | File "/app/.venv/lib/python3.10/site-packages/sqlglot/parser.py", line 1623, in parse
superset_app | return self._parse(
superset_app | File "/app/.venv/lib/python3.10/site-packages/sqlglot/parser.py", line 1695, in _parse
superset_app | self.raise_error("Invalid expression / Unexpected token")
superset_app | File "/app/.venv/lib/python3.10/site-packages/sqlglot/parser.py", line 1736, in raise_error
superset_app | raise error
superset_app | sqlglot.errors.ParseError: Invalid expression / Unexpected token. Line 1, Col: 35.
superset_app | SELECT * FROM t WHERE column1 MATCH 'word1 word2'
superset_app |
superset_app | The above exception was the direct cause of the following exception:
superset_app |
superset_app | Traceback (most recent call last):
superset_app | File "/app/.venv/lib/python3.10/site-packages/flask/app.py", line 1484, in full_dispatch_request
superset_app | rv = self.dispatch_request()
superset_app | File "/app/.venv/lib/python3.10/site-packages/flask/app.py", line 1469, in dispatch_request
superset_app | return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
superset_app | File "/app/.venv/lib/python3.10/site-packages/flask_appbuilder/security/decorators.py", line 109, in wraps
superset_app | return f(self, *args, **kwargs)
superset_app | File "/app/superset/views/base_api.py", line 120, in wraps
superset_app | duration, response = time_function(f, self, *args, **kwargs)
superset_app | File "/app/superset/utils/core.py", line 1410, in time_function
superset_app | response = func(*args, **kwargs)
superset_app | File "/app/superset/views/base_api.py", line 92, in wraps
superset_app | return f(self, *args, **kwargs)
superset_app | File "/app/superset/utils/log.py", line 304, in wrapper
superset_app | value = f(*args, **kwargs)
superset_app | File "/app/superset/sqllab/api.py", line 406, in execute_sql_query
superset_app | command_result: CommandResult = command.run()
superset_app | File "/app/superset/utils/decorators.py", line 267, in wrapped
superset_app | return on_error(ex)
superset_app | File "/app/superset/utils/decorators.py", line 232, in on_error
superset_app | raise ex
superset_app | File "/app/superset/utils/decorators.py", line 260, in wrapped
superset_app | result = func(*args, **kwargs)
superset_app | File "/app/superset/commands/sql_lab/execute.py", line 105, in run
superset_app | status = self._run_sql_json_exec_from_scratch()
superset_app | File "/app/superset/commands/sql_lab/execute.py", line 154, in _run_sql_json_exec_from_scratch
superset_app | self._set_query_limit_if_required(rendered_query)
superset_app | File "/app/superset/commands/sql_lab/execute.py", line 220, in _set_query_limit_if_required
superset_app | self._set_query_limit(rendered_query)
superset_app | File "/app/superset/commands/sql_lab/execute.py", line 230, in _set_query_limit
superset_app | db_engine_spec.get_limit_from_sql(rendered_query),
superset_app | File "/app/superset/db_engine_specs/base.py", line 1137, in get_limit_from_sql
superset_app | script = SQLScript(sql, engine=cls.engine)
superset_app | File "/app/superset/sql/parse.py", line 1242, in init
superset_app | self.statements = statement_class.split_script(script, engine)
superset_app | File "/app/superset/sql/parse.py", line 602, in split_script
superset_app | cls(ast=ast, engine=engine) for ast in cls._parse(script, engine) if ast
superset_app | File "/app/superset/sql/parse.py", line 573, in _parse
superset_app | raise SupersetParseError(script, engine, **kwargs) from ex
superset_app | superset.exceptions.SupersetParseError: Error parsing near 'MATCH' at line 1:35
Screenshots/recordings
No response
Superset version
master / latest-dev
Python version
3.9
Node version
16
Browser
Chrome
Additional context
No response
Checklist
- I have searched Superset docs and Slack and didn't find a solution to my problem.
- I have searched the GitHub issue tracker and didn't find a similar bug report.
- I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.
Activity
dosubot commentedon Dec 19, 2025
Hi @nico-gsantos! I'm Dosu and I’m helping the superset team.
Superset's SQL parser (sqlglot) does not currently support the Apache Doris MATCH operator or full text search syntax, which is why you see a ParseError when running queries like
SELECT * FROM t WHERE column1 MATCH 'word1 word2'. Superset maps Doris connections to the Doris dialect in sqlglot, but there is no explicit handling for MATCH or Doris full text search in either Superset or sqlglot, so any unrecognized syntax will fail during parsing before reaching the database (source, source).There is no built-in way to bypass or relax SQL parsing for Doris in Superset. A common workaround is to create a view in Doris that encapsulates your full text search logic, then query that view from Superset. Alternatively, supporting MATCH would require extending sqlglot's Doris dialect, which is a non-trivial code change (reference).
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
Vansh5632 commentedon Dec 30, 2025
Hi everyone,
I’ve investigated this issue, and the root cause lies in how sqlglot (which Superset uses for SQL parsing) handles the Doris dialect.
Currently, sqlglot’s Doris dialect inherits from MySQL. As a result, it treats MATCH strictly as part of the MySQL full-text search syntax (MATCH (...) AGAINST (...)) and fails to parse the Apache Doris specific infix syntax (e.g., column MATCH 'value').
I propose two ways to resolve this:
We contribute a fix directly to the sqlglot repository.
Action: Modify the Doris dialect in sqlglot to register MATCH as a binary comparison operator (similar to LIKE or EQ).
Outcome: Once merged and released in sqlglot, we simply bump the library version in Superset. This ensures better long-term support and benefits the wider community.
If an immediate fix is required before the upstream release, we can implement a temporary patch within Superset.
Action: Create a custom dialect wrapper or monkey-patch the sqlglot dialect configuration in superset/db_engine_specs/doris.py to recognize the MATCH token as a binary operator during the parsing phase.
My Proposal: I believe Option 1 is the cleanest approach. I am happy to open the PR against sqlglot to add this support.
Could the maintainers (@mistercrunch ) let me know if you prefer waiting for the upstream fix, or if you'd like to see a workaround implemented in the interim?
rusackas commentedon Jan 12, 2026
Always down with the upstream fix, when it makes more sense, and benefits more projects! I think that's probably the better solution.
Vansh5632 commentedon Jan 13, 2026
Okay cool
rusackas commentedon Oct 3, 2026
@Vansh5632 are you planning to open the upstream sqlglot PR for the Doris
MATCHsyntax? Link it here once it's up so we can track the bump.kaya-abdullah commentedon Oct 10, 2026
Still fails with the latest sqlglot (30.22.0). I opened the upstream fix: tobymao/sqlglot#8585
It covers MATCH, MATCH_ANY, MATCH_ALL, MATCH_PHRASE (with slop), MATCH_PHRASE_PREFIX, MATCH_PHRASE_EDGE, MATCH_REGEXP and USING ANALYZER. Once it's released, I can follow up here with a regression test and the sqlglot bump.
kaya-abdullah commentedon Oct 12, 2026
tobymao/sqlglot#8585 is merged. It's not in a sqlglot release yet, so once the next one is out I'll open a PR here with the sqlglot bump and a regression test for the MATCH queries.