Skip to content

Commit

Permalink
Feat(mysql): add support for the MEMBER OF operator (#1872)
Browse files Browse the repository at this point in the history
  • Loading branch information
georgesittas authored Jun 30, 2023
1 parent 8a19d7a commit 47d999c
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 1 deletion.
10 changes: 9 additions & 1 deletion sqlglot/dialects/mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,15 @@ class Tokenizer(tokens.Tokenizer):
KEYWORDS = {
**tokens.Tokenizer.KEYWORDS,
"CHARSET": TokenType.CHARACTER_SET,
"ENUM": TokenType.ENUM,
"FORCE": TokenType.FORCE,
"IGNORE": TokenType.IGNORE,
"LONGBLOB": TokenType.LONGBLOB,
"LONGTEXT": TokenType.LONGTEXT,
"MEDIUMBLOB": TokenType.MEDIUMBLOB,
"MEDIUMTEXT": TokenType.MEDIUMTEXT,
"MEMBER OF": TokenType.MEMBER_OF,
"SEPARATOR": TokenType.SEPARATOR,
"ENUM": TokenType.ENUM,
"START": TokenType.BEGIN,
"SIGNED": TokenType.BIGINT,
"SIGNED INTEGER": TokenType.BIGINT,
Expand Down Expand Up @@ -196,6 +197,13 @@ class Parser(parser.Parser):
parser.Parser.TABLE_ALIAS_TOKENS - parser.Parser.TABLE_INDEX_HINT_TOKENS
)

RANGE_PARSERS = {
**parser.Parser.RANGE_PARSERS,
TokenType.MEMBER_OF: lambda self, this: self.expression(
exp.JSONArrayContains, this=this, expression=self._parse_wrapped(self._parse_string)
),
}

FUNCTIONS = {
**parser.Parser.FUNCTIONS,
"DATE_ADD": parse_date_delta_with_interval(exp.DateAdd),
Expand Down
5 changes: 5 additions & 0 deletions sqlglot/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3624,6 +3624,11 @@ class Is(Binary, Predicate):
pass


# https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of
class JSONArrayContains(Binary, Predicate):
pass


class Kwarg(Binary):
"""Kwarg in special functions like func(kwarg => y)."""

Expand Down
3 changes: 3 additions & 0 deletions sqlglot/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2440,6 +2440,9 @@ def anyvalue_sql(self, expression: exp.AnyValue) -> str:

return self.func("ANY_VALUE", this)

def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str:
return f"{self.sql(expression, 'this')} MEMBER OF({self.sql(expression, 'expression')})"


def cached_generator(
cache: t.Optional[t.Dict[int, str]] = None
Expand Down
1 change: 1 addition & 0 deletions sqlglot/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class TokenType(AutoName):
LOCK = auto()
MAP = auto()
MATCH_RECOGNIZE = auto()
MEMBER_OF = auto()
MERGE = auto()
MOD = auto()
NATURAL = auto()
Expand Down
5 changes: 5 additions & 0 deletions tests/dialects/test_mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ def test_ddl(self):
)

def test_identity(self):
self.validate_identity("SELECT @a MEMBER OF(@c), @b MEMBER OF(@c)")
self.validate_identity("SELECT JSON_ARRAY(4, 5) MEMBER OF('[[3,4],[4,5]]')")
self.validate_identity("SELECT CAST('[4,5]' AS JSON) MEMBER OF('[[3,4],[4,5]]')")
self.validate_identity("""SELECT 'ab' MEMBER OF('[23, "abc", 17, "ab", 10]')""")
self.validate_identity("""SELECT 17 MEMBER OF('[23, "abc", 17, "ab", 10]')""")
self.validate_identity("CAST(x AS ENUM('a', 'b'))")
self.validate_identity("CAST(x AS SET('a', 'b'))")
self.validate_identity("SELECT CURRENT_TIMESTAMP(6)")
Expand Down

0 comments on commit 47d999c

Please sign in to comment.