summaryrefslogtreecommitdiffstats
path: root/sqlglot/dialects/mysql.py
diff options
context:
space:
mode:
Diffstat (limited to 'sqlglot/dialects/mysql.py')
-rw-r--r--sqlglot/dialects/mysql.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/sqlglot/dialects/mysql.py b/sqlglot/dialects/mysql.py
new file mode 100644
index 0000000..93800a6
--- /dev/null
+++ b/sqlglot/dialects/mysql.py
@@ -0,0 +1,163 @@
+from sqlglot import exp
+from sqlglot.dialects.dialect import (
+ Dialect,
+ no_ilike_sql,
+ no_paren_current_date_sql,
+ no_tablesample_sql,
+ no_trycast_sql,
+)
+from sqlglot.generator import Generator
+from sqlglot.helper import list_get
+from sqlglot.parser import Parser
+from sqlglot.tokens import Tokenizer, TokenType
+
+
+def _date_trunc_sql(self, expression):
+ unit = expression.text("unit").lower()
+
+ this = self.sql(expression.this)
+
+ if unit == "day":
+ return f"DATE({this})"
+
+ if unit == "week":
+ concat = f"CONCAT(YEAR({this}), ' ', WEEK({this}, 1), ' 1')"
+ date_format = "%Y %u %w"
+ elif unit == "month":
+ concat = f"CONCAT(YEAR({this}), ' ', MONTH({this}), ' 1')"
+ date_format = "%Y %c %e"
+ elif unit == "quarter":
+ concat = f"CONCAT(YEAR({this}), ' ', QUARTER({this}) * 3 - 2, ' 1')"
+ date_format = "%Y %c %e"
+ elif unit == "year":
+ concat = f"CONCAT(YEAR({this}), ' 1 1')"
+ date_format = "%Y %c %e"
+ else:
+ self.unsupported("Unexpected interval unit: {unit}")
+ return f"DATE({this})"
+
+ return f"STR_TO_DATE({concat}, '{date_format}')"
+
+
+def _str_to_date(args):
+ date_format = MySQL.format_time(list_get(args, 1))
+ return exp.StrToDate(this=list_get(args, 0), format=date_format)
+
+
+def _str_to_date_sql(self, expression):
+ date_format = self.format_time(expression)
+ return f"STR_TO_DATE({self.sql(expression.this)}, {date_format})"
+
+
+def _date_add(expression_class):
+ def func(args):
+ interval = list_get(args, 1)
+ return expression_class(
+ this=list_get(args, 0),
+ expression=interval.this,
+ unit=exp.Literal.string(interval.text("unit").lower()),
+ )
+
+ return func
+
+
+def _date_add_sql(kind):
+ def func(self, expression):
+ this = self.sql(expression, "this")
+ unit = expression.text("unit").upper() or "DAY"
+ expression = self.sql(expression, "expression")
+ return f"DATE_{kind}({this}, INTERVAL {expression} {unit})"
+
+ return func
+
+
+class MySQL(Dialect):
+ # https://prestodb.io/docs/current/functions/datetime.html#mysql-date-functions
+ time_mapping = {
+ "%M": "%B",
+ "%c": "%-m",
+ "%e": "%-d",
+ "%h": "%I",
+ "%i": "%M",
+ "%s": "%S",
+ "%S": "%S",
+ "%u": "%W",
+ }
+
+ class Tokenizer(Tokenizer):
+ QUOTES = ["'", '"']
+ COMMENTS = ["--", "#", ("/*", "*/")]
+ IDENTIFIERS = ["`"]
+
+ KEYWORDS = {
+ **Tokenizer.KEYWORDS,
+ "_ARMSCII8": TokenType.INTRODUCER,
+ "_ASCII": TokenType.INTRODUCER,
+ "_BIG5": TokenType.INTRODUCER,
+ "_BINARY": TokenType.INTRODUCER,
+ "_CP1250": TokenType.INTRODUCER,
+ "_CP1251": TokenType.INTRODUCER,
+ "_CP1256": TokenType.INTRODUCER,
+ "_CP1257": TokenType.INTRODUCER,
+ "_CP850": TokenType.INTRODUCER,
+ "_CP852": TokenType.INTRODUCER,
+ "_CP866": TokenType.INTRODUCER,
+ "_CP932": TokenType.INTRODUCER,
+ "_DEC8": TokenType.INTRODUCER,
+ "_EUCJPMS": TokenType.INTRODUCER,
+ "_EUCKR": TokenType.INTRODUCER,
+ "_GB18030": TokenType.INTRODUCER,
+ "_GB2312": TokenType.INTRODUCER,
+ "_GBK": TokenType.INTRODUCER,
+ "_GEOSTD8": TokenType.INTRODUCER,
+ "_GREEK": TokenType.INTRODUCER,
+ "_HEBREW": TokenType.INTRODUCER,
+ "_HP8": TokenType.INTRODUCER,
+ "_KEYBCS2": TokenType.INTRODUCER,
+ "_KOI8R": TokenType.INTRODUCER,
+ "_KOI8U": TokenType.INTRODUCER,
+ "_LATIN1": TokenType.INTRODUCER,
+ "_LATIN2": TokenType.INTRODUCER,
+ "_LATIN5": TokenType.INTRODUCER,
+ "_LATIN7": TokenType.INTRODUCER,
+ "_MACCE": TokenType.INTRODUCER,
+ "_MACROMAN": TokenType.INTRODUCER,
+ "_SJIS": TokenType.INTRODUCER,
+ "_SWE7": TokenType.INTRODUCER,
+ "_TIS620": TokenType.INTRODUCER,
+ "_UCS2": TokenType.INTRODUCER,
+ "_UJIS": TokenType.INTRODUCER,
+ "_UTF8": TokenType.INTRODUCER,
+ "_UTF16": TokenType.INTRODUCER,
+ "_UTF16LE": TokenType.INTRODUCER,
+ "_UTF32": TokenType.INTRODUCER,
+ "_UTF8MB3": TokenType.INTRODUCER,
+ "_UTF8MB4": TokenType.INTRODUCER,
+ }
+
+ class Parser(Parser):
+ STRICT_CAST = False
+
+ FUNCTIONS = {
+ **Parser.FUNCTIONS,
+ "DATE_ADD": _date_add(exp.DateAdd),
+ "DATE_SUB": _date_add(exp.DateSub),
+ "STR_TO_DATE": _str_to_date,
+ }
+
+ class Generator(Generator):
+ NULL_ORDERING_SUPPORTED = False
+
+ TRANSFORMS = {
+ **Generator.TRANSFORMS,
+ exp.CurrentDate: no_paren_current_date_sql,
+ exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP",
+ exp.ILike: no_ilike_sql,
+ exp.TableSample: no_tablesample_sql,
+ exp.TryCast: no_trycast_sql,
+ exp.DateAdd: _date_add_sql("ADD"),
+ exp.DateSub: _date_add_sql("SUB"),
+ exp.DateTrunc: _date_trunc_sql,
+ exp.StrToDate: _str_to_date_sql,
+ exp.StrToTime: _str_to_date_sql,
+ }