From f94bee6190aa1e29ed26b5657dae3c1d8fbb9201 Mon Sep 17 00:00:00 2001 From: Klemen Tusar Date: Sun, 16 Nov 2025 14:29:23 +0000 Subject: [PATCH 1/2] :safety_vest: add support for SQLite's `current_timestamp` function in datetime handling --- src/sqlite3_to_mysql/transporter.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/sqlite3_to_mysql/transporter.py b/src/sqlite3_to_mysql/transporter.py index 7635669..a7cc50f 100644 --- a/src/sqlite3_to_mysql/transporter.py +++ b/src/sqlite3_to_mysql/transporter.py @@ -82,6 +82,10 @@ class SQLite3toMySQL(SQLite3toMySQLAttributes): r"^(datetime|date|time)\s*\(\s*'now'(?:\s*,\s*'(localtime|utc)')?\s*\)$", re.IGNORECASE, ) + SQLITE_CURRENT_TS_FUNC: t.Pattern[str] = re.compile( + r"^(datetime|date|time)\s*\(\s*current_timestamp(?:\s*,\s*'(localtime|utc)')?\s*\)$", + re.IGNORECASE, + ) STRFTIME_NOW: t.Pattern[str] = re.compile( r"^strftime\s*\(\s*'([^']+)'\s*,\s*'now'(?:\s*,\s*'(localtime|utc)')?\s*\)$", re.IGNORECASE, @@ -577,6 +581,10 @@ def _translate_default_for_mysql(self, column_type: str, default: str) -> str: s: str = self._strip_wrapping_parentheses(raw) u: str = s.upper() + sqlite_current_ts_match: t.Optional[re.Match[str]] = self.SQLITE_CURRENT_TS_FUNC.match(s) + sqlite_current_ts_func: t.Optional[str] = ( + sqlite_current_ts_match.group(1).lower() if sqlite_current_ts_match else None + ) # NULL passthrough if u == "NULL": @@ -590,6 +598,7 @@ def _translate_default_for_mysql(self, column_type: str, default: str) -> str: if base.startswith("TIMESTAMP") and ( self.CURRENT_TS.match(s) or (self.SQLITE_NOW_FUNC.match(s) and s.lower().startswith("datetime")) + or sqlite_current_ts_func == "datetime" or self.STRFTIME_NOW.match(s) ): len_match: t.Optional[re.Match[str]] = self.COLUMN_LENGTH_PATTERN.search(column_type) @@ -609,6 +618,7 @@ def _translate_default_for_mysql(self, column_type: str, default: str) -> str: if base.startswith("DATETIME") and ( self.CURRENT_TS.match(s) or (self.SQLITE_NOW_FUNC.match(s) and s.lower().startswith("datetime")) + or sqlite_current_ts_func == "datetime" or self.STRFTIME_NOW.match(s) ): if not self._allow_current_ts_dt: @@ -633,6 +643,7 @@ def _translate_default_for_mysql(self, column_type: str, default: str) -> str: self.CURRENT_DATE.match(s) or self.CURRENT_TS.match(s) # map CURRENT_TIMESTAMP → CURRENT_DATE for DATE or (self.SQLITE_NOW_FUNC.match(s) and s.lower().startswith("date")) + or sqlite_current_ts_func == "date" or self.STRFTIME_NOW.match(s) ) and self._allow_expr_defaults @@ -647,6 +658,7 @@ def _translate_default_for_mysql(self, column_type: str, default: str) -> str: self.CURRENT_TIME.match(s) or self.CURRENT_TS.match(s) # map CURRENT_TIMESTAMP → CURRENT_TIME for TIME or (self.SQLITE_NOW_FUNC.match(s) and s.lower().startswith("time")) + or sqlite_current_ts_func == "time" or self.STRFTIME_NOW.match(s) ) and self._allow_expr_defaults From e703708808fc6f5127289f14104448e6da79eab7 Mon Sep 17 00:00:00 2001 From: Klemen Tusar Date: Sun, 16 Nov 2025 14:29:37 +0000 Subject: [PATCH 2/2] :white_check_mark: enhance datetime mapping to include local and UTC timestamp handling --- tests/unit/sqlite3_to_mysql_test.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/unit/sqlite3_to_mysql_test.py b/tests/unit/sqlite3_to_mysql_test.py index d712a99..28278ff 100644 --- a/tests/unit/sqlite3_to_mysql_test.py +++ b/tests/unit/sqlite3_to_mysql_test.py @@ -2014,6 +2014,19 @@ def _mk(*, expr: bool, ts_dt: bool, fsp: bool) -> SQLite3toMySQL: ("TIMESTAMP(3)", "CURRENT_TIMESTAMP", {"expr": False, "ts_dt": True, "fsp": True}, "CURRENT_TIMESTAMP(3)"), # SQLite-style now -> map to CURRENT_TIMESTAMP (with FSP when allowed) ("DATETIME(2)", "datetime('now')", {"expr": False, "ts_dt": True, "fsp": True}, "CURRENT_TIMESTAMP(2)"), + # datetime(current_timestamp, ...) should also map to CURRENT/UTC TIMESTAMP + ( + "DATETIME", + "datetime(current_timestamp, 'localtime')", + {"expr": False, "ts_dt": True, "fsp": False}, + "CURRENT_TIMESTAMP", + ), + ( + "DATETIME(3)", + "datetime(current_timestamp, 'utc')", + {"expr": False, "ts_dt": True, "fsp": True}, + "UTC_TIMESTAMP(3)", + ), # --- DATE mapping (from 'now' forms or CURRENT_TIMESTAMP) --- # Only map when expression defaults are allowed ("DATE", "datetime('now')", {"expr": True, "ts_dt": False, "fsp": False}, "CURRENT_DATE"),