feat(data-import): 重构大文件导入与安全任务运行时

- SQL、CSV、JSON 与 XLSX 改为资源受限的流式解析,并支持压缩、编码和方言预检

- 增加遇错停止/继续策略、持久任务、错误行导出、源文件身份与安全取消

- 为数据库驱动补齐上下文事务和写入结果未知语义,避免失败重放与脏会话复用
This commit is contained in:
Syngnat
2026-08-08 20:51:23 +08:00
parent 4df879ccde
commit 390a249105
81 changed files with 15267 additions and 625 deletions

View File

@@ -4419,17 +4419,101 @@
"data_grid.view.result_view": "Просмотр результата",
"data_grid.view.table": "Таблица",
"data_grid.view.text": "Текст",
"data_import.capability.loading": "Проверяется поддержка импорта для этого подключения...",
"data_import.capability.details.formats": "Форматы файлов",
"data_import.capability.details.encodings": "Кодировки",
"data_import.capability.details.compressions": "Сжатие",
"data_import.capability.details.directives": "Клиентские директивы",
"data_import.capability.reason.capability_unavailable": "Сведения о поддержке импорта недоступны. Выбор файла и запуск отключены.",
"data_import.capability.reason.data_import_restricted": "Импорт данных отключён политикой защиты этого подключения.",
"data_import.capability.reason.database_runtime_unavailable": "Среда выполнения базы данных недоступна, поэтому поддержку импорта проверить нельзя.",
"data_import.capability.reason.database_type_unsupported": "Этот тип базы данных не поддерживается в текущем режиме импорта.",
"data_import.capability.reason.pinned_session_unavailable": "Импорт SQL-файла отключён: драйвер не может предоставить проверенный закреплённый сеанс.",
"data_import.capability.reason.sql_file_import_restricted": "Импорт SQL-файла отключён защитой скриптов или структуры.",
"data_import.capability.reason.table_import_runtime_unavailable": "Среда выполнения этого драйвера не предоставляет интерфейс импорта таблиц.",
"data_import.capability.reason.unsupported": "Текущий режим импорта недоступен для выбранного подключения.",
"data_import.capability.rpc_failed": "Не удалось проверить поддержку импорта. Проверьте подключение и повторите попытку.",
"data_import.history.action.delete": "Удалить запись",
"data_import.history.action.details": "Подробнее",
"data_import.history.action.export_errors": "Экспортировать отклонённые строки",
"data_import.history.action.refresh": "Обновить",
"data_import.history.confirm.delete_content": "Удалить запись завершённого импорта? Сначала экспортируйте нужные отклонённые строки.",
"data_import.history.confirm.delete_title": "Удалить запись импорта",
"data_import.history.description": "Просмотр последних импортов таблиц и SQL-файлов. Выполняемые задания удалить нельзя.",
"data_import.history.detail.job_id": "ID задания: {{id}}",
"data_import.history.detail.outcome_unknown": "Сбойный пакет мог быть записан частично. Перед повторным импортом проверьте целевые данные.",
"data_import.history.detail.stage": "Этап: {{stage}}",
"data_import.history.empty": "История импорта пуста",
"data_import.history.error.delete_failed": "Не удалось удалить запись импорта",
"data_import.history.error.delete_failed_detail": "Не удалось удалить запись импорта: {{detail}}",
"data_import.history.error.details_failed": "Не удалось загрузить сведения об импорте",
"data_import.history.error.details_failed_detail": "Не удалось загрузить сведения об импорте: {{detail}}",
"data_import.history.error.export_failed": "Не удалось экспортировать отклонённые строки",
"data_import.history.error.export_failed_detail": "Не удалось экспортировать отклонённые строки: {{detail}}",
"data_import.history.error.load_failed": "Не удалось загрузить историю импорта",
"data_import.history.error.load_failed_detail": "Не удалось загрузить историю импорта: {{detail}}",
"data_import.history.kind.sql": "SQL-файл",
"data_import.history.kind.table": "Данные таблицы",
"data_import.history.message.deleted": "Запись импорта удалена",
"data_import.history.message.exported": "Отклонённые строки экспортированы",
"data_import.history.progress": "Обработано {{current}} · Успешно {{success}} · Пропущено {{skipped}} · Ошибок {{failed}}",
"data_import.history.status.cancelled": "Отменено",
"data_import.history.status.completed": "Завершено",
"data_import.history.status.failed": "Ошибка",
"data_import.history.status.interrupted": "Прервано",
"data_import.history.status.partial": "Завершено с ошибками",
"data_import.history.status.preparing": "Подготовка",
"data_import.history.status.running": "Выполняется",
"data_import.history.status.stopping": "Останавливается",
"data_import.history.status.unknown": "Результат неизвестен",
"data_import.history.title": "История импорта",
"data_import.workbench.action.cancel_database_import": "Отменить импорт",
"data_import.workbench.action.change_file": "Сменить файл",
"data_import.workbench.action.change_sql_file": "Сменить SQL-файл",
"data_import.workbench.action.retry_database_import": "Повторить импорт базы данных",
"data_import.workbench.action.retry_database_import": "Повторно выполнить весь SQL-файл",
"data_import.workbench.action.select_file": "Выбрать файл и открыть предпросмотр",
"data_import.workbench.action.select_sql_file": "Выбрать SQL-файл",
"data_import.workbench.action.start_database_import": "Начать импорт базы данных",
"data_import.workbench.advanced.conflict.skip_duplicates": "Пропускать строки с повторяющимся ключом",
"data_import.workbench.advanced.conflict.stop": "Остановиться при конфликте",
"data_import.workbench.advanced.conflict.upsert": "Вставить или обновить",
"data_import.workbench.advanced.conflict_keys": "Столбцы ключа конфликта",
"data_import.workbench.advanced.conflict_keys_not_mapped": "Столбцы ключа конфликта должны входить в выбранные сопоставления: {{columns}}",
"data_import.workbench.advanced.conflict_keys_placeholder": "Например: id, tenant_id",
"data_import.workbench.advanced.conflict_keys_required": "Для вставки или обновления укажите хотя бы один столбец ключа конфликта.",
"data_import.workbench.advanced.conflict_unsupported": "Это подключение не поддерживает сохранённую политику повторяющихся ключей. Перед импортом выберите поддерживаемую политику.",
"data_import.workbench.advanced.conflict_policy": "Обработка повторяющихся ключей",
"data_import.workbench.advanced.delimiter": "Разделитель CSV",
"data_import.workbench.advanced.delimiter.auto": "Определять автоматически",
"data_import.workbench.advanced.delimiter.comma": "Запятая (,)",
"data_import.workbench.advanced.delimiter.pipe": "Вертикальная черта (|)",
"data_import.workbench.advanced.delimiter.semicolon": "Точка с запятой (;)",
"data_import.workbench.advanced.delimiter.tab": "Табуляция",
"data_import.workbench.advanced.description": "Эти настройки применяются к предпросмотру и импорту и сохраняются на этом устройстве.",
"data_import.workbench.advanced.empty_string_as_null": "Считать пустые строки значением NULL",
"data_import.workbench.advanced.encoding": "Кодировка текста",
"data_import.workbench.advanced.encoding.auto": "Определять автоматически",
"data_import.workbench.advanced.encoding.gb18030": "GB18030",
"data_import.workbench.advanced.encoding.utf16be": "UTF-16 BE",
"data_import.workbench.advanced.encoding.utf16le": "UTF-16 LE",
"data_import.workbench.advanced.encoding.utf8": "UTF-8",
"data_import.workbench.advanced.header_row": "Строка заголовка",
"data_import.workbench.advanced.null_token": "Маркер NULL (пустое значение отключает его)",
"data_import.workbench.advanced.sheet_name": "Имя листа (пустое значение выбирает первый лист)",
"data_import.workbench.advanced.title": "Расширенные параметры импорта таблицы",
"data_import.workbench.confirm.rerun_content": "Весь SQL-файл будет выполнен с начала. Зафиксированные операторы предыдущего запуска не откатываются и могут выполниться повторно.",
"data_import.workbench.confirm.rerun_title": "Повторно выполнить весь SQL-файл?",
"data_import.workbench.description": "Выберите целевую таблицу и файл данных, затем проверьте данные, настройте сопоставление столбцов и запустите импорт.",
"data_import.workbench.description.database": "Выберите подключение и SQL-файл для импорта всей базы данных. Для обычных SQL-файлов можно при необходимости указать базу данных по умолчанию.",
"data_import.workbench.helper.file_formats": "Поддерживаются файлы CSV, JSON, XLSX и XLS.",
"data_import.workbench.helper.sql_file": "Поддерживаются файлы .sql. Выбор файла не запускает импорт автоматически.",
"data_import.workbench.error_policy.continue": родолжать после ошибок SQL",
"data_import.workbench.error_policy.continue_description": "Ошибки записываются, выполнение продолжается. В MySQL/MariaDB операторы выполняются по одному, чтобы не повторять сбойные пакеты; большие файлы обрабатываются медленнее, а уже зафиксированные операторы автоматически не откатываются.",
"data_import.workbench.error_policy.continue_table": "Продолжать после ошибок строк",
"data_import.workbench.error_policy.continue_table_description": "С самого начала строки записываются по одной, ошибки фиксируются, после чего импорт продолжается. Сбойные пакеты не запускаются и не повторяются; большие файлы обрабатываются медленнее, а записанные данные автоматически не откатываются.",
"data_import.workbench.error_policy.stop_description": "Рекомендуется. Остановиться при первой ошибке SQL без повторного выполнения сбойного пакета. В нетранзакционных таблицах могут сохраниться частичные записи.",
"data_import.workbench.error_policy.stop_table_description": "Рекомендуется. Использовать пакетную запись и остановиться при первой ошибке пакета без его повтора. Если API вернул ошибку, пакет мог быть записан частично; проверьте целевую таблицу.",
"data_import.workbench.error_policy.title": "Обработка ошибок",
"data_import.workbench.helper.file_formats": "Поддерживаются файлы CSV, JSON и XLSX.",
"data_import.workbench.helper.sql_file": "Поддерживаются файлы .sql и .sql.gz. Выбор файла не запускает импорт автоматически.",
"data_import.workbench.label.connection": "Подключение",
"data_import.workbench.label.database": "База данных",
"data_import.workbench.label.default_database": "База данных по умолчанию (необязательно)",
@@ -4446,7 +4530,9 @@
"data_import.workbench.mode.database": "Импортировать базу данных",
"data_import.workbench.mode.table": "Импортировать таблицу",
"data_import.workbench.notice.gonavi_mysql_restore": "Резервные копии MySQL, созданные GoNavi, восстанавливают базу данных с именем, указанным в файле. Для других SQL-файлов можно использовать выбранную выше необязательную базу данных по умолчанию.",
"data_import.workbench.notice.continue_on_error": "В режиме продолжения ошибки записываются, а последующие операторы выполняются. Чтобы избежать повторной записи в нетранзакционные таблицы, MySQL/MariaDB выполняет операторы по одному и не повторяет сбойные пакеты; большие файлы могут обрабатываться заметно медленнее. Уже зафиксированные операторы автоматически не откатываются.",
"data_import.workbench.notice.partial_execution": "SQL-инструкции выполняются последовательно в потоковом режиме. Инструкции, завершённые до ошибки или отмены, не откатываются автоматически. Заранее проверьте целевое подключение и резервную копию.",
"data_import.workbench.notice.stop_on_error": "Выполнение останавливается при первой ошибке SQL без повторного выполнения сбойного пакета. Выполняется попытка отката, но в нетранзакционных таблицах могут сохраниться прежние записи. Ранее зафиксированные инструкции автоматически не откатываются.",
"data_import.workbench.placeholder.loading_databases": "Загрузка баз данных...",
"data_import.workbench.placeholder.loading_tables": "Загрузка таблиц...",
"data_import.workbench.placeholder.select_connection": "Выберите подключение",
@@ -4455,6 +4541,9 @@
"data_import.workbench.placeholder.select_default_database": "Необязательно: выберите базу данных по умолчанию",
"data_import.workbench.placeholder.select_table": "Выберите целевую таблицу",
"data_import.workbench.progress.bytes": "Обработка файла: {{processed}} / {{total}}",
"data_import.workbench.progress.throughput": "Скорость: {{rate}}/с",
"data_import.workbench.progress.eta": "Осталось: {{duration}}",
"data_import.workbench.progress.skipped": "Пропущено строк: {{count}}",
"data_import.workbench.progress.statements": "Ход выполнения: выполнено {{executed}}, с ошибкой {{failed}}",
"data_import.workbench.section.target": "Цель импорта",
"data_import.workbench.state.awaiting_file_description": "После выбора цели выберите файл данных, чтобы просмотреть содержимое и настроить сопоставление столбцов.",
@@ -4464,6 +4553,7 @@
"data_import.workbench.state.cancelled": "Отменено",
"data_import.workbench.state.cancelling": "Отмена...",
"data_import.workbench.state.completed": "Импорт завершён",
"data_import.workbench.state.completed_with_errors": "Импорт завершён с ошибками",
"data_import.workbench.state.failed": "Ошибка импорта",
"data_import.workbench.state.ready_sql_description": "Проверьте цель и предупреждение о рисках, затем запустите импорт вручную.",
"data_import.workbench.state.ready_sql_title": "SQL-файл готов",
@@ -5581,6 +5671,7 @@
"driver_manager.version.unlabeled": "Версия не указана",
"file.backend.dialog.export_connections": "Экспорт подключений",
"file.backend.dialog.export_data": "Экспорт данных",
"file.backend.dialog.export_import_errors": "Экспорт отклонённых строк импорта",
"file.backend.dialog.export_database_sql": "Экспорт {{database}} (SQL)",
"file.backend.dialog.export_query_result": "Экспорт результата запроса",
"file.backend.dialog.export_table": "Экспорт {{table}}",
@@ -5627,8 +5718,15 @@
"file.backend.error.import_excel_parse_failed": "Не удалось разобрать Excel: {{detail}}",
"file.backend.error.import_excel_read_failed": "Не удалось прочитать Excel: {{detail}}",
"file.backend.error.import_file_empty": "Путь к файлу не может быть пустым",
"file.backend.error.import_error_artifact_not_found": "Данные для экспорта отклонённых строк недоступны или устарели",
"file.backend.error.import_job_not_found": "Задание импорта не найдено",
"file.backend.error.import_job_persist": "Не удалось сохранить состояние задания импорта: {{detail}}",
"file.backend.error.import_job_running": "Задание импорта ещё выполняется и не может быть удалено",
"file.backend.error.import_resume_unavailable": "Этот импорт нельзя безопасно возобновить",
"file.backend.error.import_source_changed": "Источник импорта изменился после предпросмотра. Выберите файл заново и повторите предпросмотр.",
"file.backend.error.import_json_parse_failed": "Не удалось разобрать JSON: {{detail}}",
"file.backend.error.import_json_root_not_array": "Корень JSON должен быть массивом",
"file.backend.error.import_stopped_on_error": "Импорт таблицы остановлен из-за ошибки. Подтвержден импорт {{imported}} строк, зарегистрировано ошибок: {{failed}}. {{detail}}",
"file.backend.error.import_unsupported_format": "Неподдерживаемый формат файла",
"file.backend.error.invalid_export_mode": "Недопустимый режим экспорта",
"file.backend.error.mysql_workbench_no_connections": "В XML не найдены допустимые конфигурации подключений",
@@ -5656,11 +5754,14 @@
"file.backend.error.selected_path_not_sql_file": "Выбранный путь не является SQL-файлом",
"file.backend.error.sql_file_batch_execution_failed": "Ошибка пакетного выполнения, начиная с инструкции {{index}}: {{detail}}",
"file.backend.error.sql_file_batch_rollback_failed": "Ошибка пакетного выполнения: {{detail}}; ошибка отката: {{rollbackDetail}}",
"file.backend.error.sql_file_execution_failed_summary": "Выполнение SQL-файла прервано после {{count}} инструкций: {{detail}}",
"file.backend.error.sql_file_exists": "SQL-файл уже существует",
"file.backend.error.sql_file_extension_required": "Поддерживаются только SQL-файлы",
"file.backend.error.sql_file_name_no_separator": "Имя SQL-файла не может содержать разделители пути",
"file.backend.error.sql_file_name_required": "Имя SQL-файла не может быть пустым",
"file.backend.error.sql_file_statement_execution_failed": "Ошибка выполнения инструкции {{index}}: {{detail}}",
"file.backend.error.sql_file_stopped_on_error_summary": "Выполнение SQL-файла остановлено. Выполнено инструкций: {{success}}, обнаружено ошибок: {{failed}}. {{detail}}",
"file.backend.error.sql_file_unclosed_transaction": "SQL-файл завершился до закрытия транзакции. Импорт остановлен, незавершённая транзакция будет очищена.",
"file.backend.error.table_data_batch_limit": "За один раз можно обработать не более {{max}} таблиц; сейчас выбрано {{count}}",
"file.backend.error.table_data_clear_failed": "Не удалось очистить {{table}}: {{detail}}",
"file.backend.error.table_data_clear_failed_partial": "Не удалось очистить {{table}}: {{detail}}. Предупреждение: первые {{count}} таблиц уже очищены, их нельзя восстановить",
@@ -5698,6 +5799,7 @@
"file.backend.message.export_completed": "Экспорт завершен",
"file.backend.message.import_no_data": "Нет данных для импорта",
"file.backend.message.import_row_failed": "Ошибка импорта строки {{index}}: {{detail}}",
"file.backend.message.import_errors_exported": "Отклонённые строки импорта экспортированы",
"file.backend.message.import_summary": "Импортировано: {{imported}}, ошибок: {{failed}}",
"file.backend.message.statement_failed": "Ошибка выполнения инструкции {{index}}: {{detail}}\n SQL: {{sql}}",
"file.backend.message.table_data_clear_succeeded": "Очистка выполнена успешно",
@@ -5734,9 +5836,12 @@
"find_in_database.tooltip.collapse_details": "Свернуть подробности",
"find_in_database.tooltip.view_details": "Показать подробности",
"import_preview.action.start": "Начать импорт",
"import_preview.action.export_rejected_rows": "Экспортировать отклонённые строки",
"import_preview.error.connection_config_not_found": "Конфигурация подключения не найдена",
"import_preview.error.import_failed": "Не удалось выполнить импорт",
"import_preview.error.import_failed_detail": "Не удалось выполнить импорт: {{detail}}",
"import_preview.error.export_rejected_rows_failed": "Не удалось экспортировать отклонённые строки",
"import_preview.error.export_rejected_rows_failed_detail": "Не удалось экспортировать отклонённые строки: {{detail}}",
"import_preview.error.preview_failed": "Не удалось выполнить предпросмотр",
"import_preview.error.preview_failed_detail": "Не удалось выполнить предпросмотр: {{detail}}",
"import_preview.error.target_columns_failed": "Не удалось загрузить столбцы целевой таблицы",
@@ -5754,12 +5859,23 @@
"import_preview.preview.description": "Ниже показаны первые 5 строк. Начните импорт после проверки данных.",
"import_preview.preview.field_list": "Список полей:",
"import_preview.preview.summary": "{{rows}} строк и {{columns}} полей",
"import_preview.preview.summary_sample": "Показано строк выборки: {{rows}}; общее число строк не сканировалось. Полей: {{columns}}",
"import_preview.preview.table_title": "Предпросмотр данных (первые 5 строк):",
"import_preview.progress.error_count": "Ошибок {{count}}",
"import_preview.progress.processed_rows": "Обработано {{current}} / {{total}} строк",
"import_preview.progress.processed_rows_unknown": "Обработано строк: {{current}}",
"import_preview.progress.success_count": "Успешно {{count}}",
"import_preview.stage.prepare": "Подготовка импорта",
"import_preview.stage.preflight": "Предварительная проверка",
"import_preview.stage.read": "Чтение исходного файла",
"import_preview.stage.parse": "Разбор исходного файла",
"import_preview.stage.write": "Запись строк",
"import_preview.stage.finalize": "Завершение результата",
"import_preview.result.completed": "Импорт завершен",
"import_preview.result.batch_outcome_unknown": "Сбойный пакет мог быть записан частично. Проверьте целевую таблицу перед повторной попыткой.",
"import_preview.result.error_logs": "Журнал ошибок:",
"import_preview.result.error_count": "Зарегистрировано ошибок: {{count}}",
"import_preview.result.error_logs_omitted": "Не показано дополнительных сведений об ошибках: {{count}}.",
"import_preview.result.failed_rows": "Строк с ошибками: {{count}}",
"import_preview.result.success_rows": "Успешно импортировано строк: {{count}}",
"import_preview.status.importing": "Импорт данных...",
@@ -5770,6 +5886,7 @@
"jvm.backend.connection_error.agent.base_url_invalid.summary": "Подключение Agent не удалось: Agent Base URL недействителен.",
"jvm.backend.connection_error.agent.base_url_required": "Подключение Agent не удалось: Agent Base URL отсутствует.",
"import_preview.result.stopped": "Импорт остановлен (зафиксированные данные не были отменены)",
"import_preview.result.stopped_on_error": "Импорт остановлен из-за ошибки",
"jvm.backend.connection_error.agent.connection_refused.help": "Убедитесь, что Java service запущен с GoNavi Agent через `-javaagent`, и проверьте Base URL, port mapping и правила firewall.",
"jvm.backend.connection_error.agent.connection_refused.summary": "Подключение Agent не удалось: целевой management port Agent не слушается или адрес недоступен.",
"jvm.backend.connection_error.agent.forbidden.help": "Убедитесь, что источник клиента, настройки authentication и access policy Agent разрешают GoNavi доступ.",
@@ -7731,12 +7848,13 @@
"sidebar.sql_file_exec.executed_label": "Выполнено: ",
"sidebar.sql_file_exec.file_size": "Размер файла: ",
"sidebar.sql_file_exec.message.already_running": "Задача выполнения внешнего SQL уже запущена",
"sidebar.sql_file_exec.rows_separator": " строк | Ошибок: ",
"sidebar.sql_file_exec.rows_suffix": " строк",
"sidebar.sql_file_exec.statements_separator": " операторов | Ошибок: ",
"sidebar.sql_file_exec.statements_suffix": " операторов",
"sidebar.sql_file_exec.status.cancelled": "Отменено",
"sidebar.sql_file_exec.status.done": "Готово",
"sidebar.sql_file_exec.status.error": "Ошибка",
"sidebar.sql_file_exec.status.running": "Выполняется",
"sidebar.sql_file_exec.status.stopping": "Останавливается...",
"sidebar.sql_file_exec.status_label": "Статус: ",
"sidebar.sql_file_exec.title": "Запустить внешний SQL-файл",
"sidebar.sql_file_exec.workbench.action.clear_history": "Очистить историю",