|
40 | 40 | convert_date, |
41 | 41 | convert_decimal, |
42 | 42 | convert_timedelta, |
| 43 | + sqlite_jsonb_column_expression, |
43 | 44 | unicase_compare, |
44 | 45 | ) |
45 | 46 |
|
@@ -304,6 +305,13 @@ def _get_table_info(self, table_name: str) -> t.List[t.Dict[str, t.Any]]: |
304 | 305 | self._sqlite_cur.execute(f'PRAGMA {pragma}("{quoted_table_name}")') |
305 | 306 | return [dict(row) for row in self._sqlite_cur.fetchall()] |
306 | 307 |
|
| 308 | + @staticmethod |
| 309 | + def _declared_type_is_jsonb(column_type: t.Optional[str]) -> bool: |
| 310 | + """Return True when a SQLite column is declared as JSONB.""" |
| 311 | + if not column_type: |
| 312 | + return False |
| 313 | + return column_type.strip().upper().startswith("JSONB") |
| 314 | + |
307 | 315 | def _get_table_primary_key_columns(self, table_name: str) -> t.List[str]: |
308 | 316 | """Return visible primary key columns ordered by their PK sequence.""" |
309 | 317 | primary_key_rows: t.List[t.Dict[str, t.Any]] = sorted( |
@@ -516,6 +524,8 @@ def _translate_type_from_sqlite_to_mysql_legacy(self, column_type: str) -> str: |
516 | 524 | return "TINYINT(1)" |
517 | 525 | if data_type.startswith(("REAL", "DOUBLE", "FLOAT", "DECIMAL", "DEC", "FIXED")): |
518 | 526 | return full_column_type |
| 527 | + if data_type in {"JSONB"} or data_type.startswith("JSONB"): |
| 528 | + return "JSON" |
519 | 529 | if data_type not in MYSQL_COLUMN_TYPES: |
520 | 530 | return self._mysql_string_type |
521 | 531 | return full_column_type |
@@ -1323,8 +1333,32 @@ def transfer(self) -> None: |
1323 | 1333 | "view" if object_type == "view" else "table", |
1324 | 1334 | table_name, |
1325 | 1335 | ) |
| 1336 | + table_column_info: t.List[t.Dict[str, t.Any]] = self._get_table_info(table_name) |
| 1337 | + visible_columns: t.List[t.Dict[str, t.Any]] = [ |
| 1338 | + column for column in table_column_info if column.get("hidden", 0) != 1 |
| 1339 | + ] |
| 1340 | + jsonb_columns: t.Set[str] = { |
| 1341 | + str(column["name"]) |
| 1342 | + for column in visible_columns |
| 1343 | + if column.get("name") and self._declared_type_is_jsonb(column.get("type")) |
| 1344 | + } |
| 1345 | + |
| 1346 | + select_parts: t.List[str] = [] |
1326 | 1347 | if transfer_rowid: |
1327 | | - select_list: str = 'rowid as "rowid", *' |
| 1348 | + select_parts.append('rowid AS "rowid"') |
| 1349 | + |
| 1350 | + for column in visible_columns: |
| 1351 | + column_name: t.Optional[str] = column.get("name") |
| 1352 | + if not column_name: |
| 1353 | + continue |
| 1354 | + quoted_column: str = self._sqlite_quote_ident(column_name) |
| 1355 | + if column_name in jsonb_columns: |
| 1356 | + select_parts.append(sqlite_jsonb_column_expression(quoted_column)) |
| 1357 | + else: |
| 1358 | + select_parts.append(f'"{quoted_column}"') |
| 1359 | + |
| 1360 | + if select_parts: |
| 1361 | + select_list = ", ".join(select_parts) |
1328 | 1362 | else: |
1329 | 1363 | select_list = "*" |
1330 | 1364 | self._sqlite_cur.execute(f'SELECT {select_list} FROM "{quoted_table_name}"') |
|
0 commit comments