Cloud SQL: по умолчанию клиент Python API API использует набор символов utf8mb3 при импорте файлов CSV - PullRequest
0 голосов
/ 14 января 2019

Я использую API импорта Google Cloud для загрузки файла CSV из Google Cloud Storage в базу данных Cloud SQL MySQL 5.7:

https://cloud.google.com/sql/docs/mysql/admin-api/v1beta4/instances/import

API импорта генерирует команду LOAD DATA INFILE для базы данных MySQL, которая принимает набор символов utf8. Тем не менее, данные в моих файлах CSV используют кодировку utf8mb4, которая является надмножеством utf8. Это приводит к сбою процесса загрузки, когда некоторые строки не могут быть закодированы в 'utf8':

Exception: CloudSQL Exception: {'kind': 'sql#operation', 'selfLink': 'https://www.googleapis.com/sql/v1beta4/projects/***', 'targetProject': '***', 'targetId': '***', 'targetLink': 'https://www.googleapis.com/sql/v1beta4/projects/***', 'name': '0211c99e-0633-42f1-9ee1-069473308273', 'operationType': 'IMPORT', 'status': 'RUNNING', 'user': '***', 'insertTime': '2019-01-14T02:36:39.861Z', 'startTime': '2019-01-14T02:36:39.972Z', 'error': {'kind': 'sql#operationErrors', 'errors': [{'kind': 'sql#operationError', 'code': 'ERROR_RDBMS', 'message': "Import CSV error: Error 1300: Invalid utf8 character string: ''Afikanisitani|'Apekanikana|A Phu Han (Afghanistan)|A Phú Hãn '\n"}]}, 'importContext': {'kind': 'sql#importContext', 'uri': '***', 'database': '**', 'importUser': '', 'csvImportOptions': {'table': '***'}}}

Соответствующий фрагмент: "'message':" Ошибка импорта CSV: Ошибка 1300: Неверная строка символов utf8: "

Есть ли способ добавить 'utf8mb4' CHARACTER SET, используя API импорта (или любой другой набор символов в этом отношении)?

Я попытался поэкспериментировать с добавлением 'набора символов': 'utf8mb4' в словаре 'csvImportOptions', но похоже, что API импорта ожидает только ключи 'table' и 'columns' в этом словаре.

Обратите внимание: если я напрямую запускаю команду LOAD DATA INFILE из клиента MySQL, я могу импортировать CSV без проблем:

LOAD DATA INFILE 'myCSVFile.csv'
INTO TABLE 'my table'
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
from pprint import pprint

from googleapiclient import discovery
from oauth2client.client import GoogleCredentials

credentials = GoogleCredentials.get_application_default()

service = discovery.build('sqladmin', 'v1beta4', credentials=credentials)

# Project ID of the project that contains the instance.
project = 'my-project'  # TODO: Update placeholder value.

# Cloud SQL instance ID. This does not include the project ID.
instance = 'my-instance'  # TODO: Update placeholder value.

instances_import_request_body = {
    "importContext": {
        "kind": "sql#importContext",
        "fileType": "CSV",
        "uri": gcs_uri,
        "database": database,
        "csvImportOptions": {
            "table": table
        }
    }
}

request = service.instances().import_(project=project, instance=instance, body=instances_import_request_body)
response = request.execute()

ДОПОЛНИТЕЛЬНАЯ ТОЧКА ДАННЫХ Для меня очевидно, что запрос LOAD DATA INFILE, который генерирует API Google, по умолчанию использует набор символов utf8.

Сбой с таким же сообщением об ошибке, как API

LOAD DATA INFILE 'problematic.csv'
INTO TABLE my_table
**CHARACTER SET utf8**
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '\"'
ESCAPED BY '\"'

ERROR 1300 (HY000): Invalid utf8 character string: ''Afikanisitani|'Apekanikana|A Phu Han (Afghanistan)|A Phú Hãn '

Работает:

LOAD DATA INFILE 'problematic.csv'
INTO TABLE my_table
**CHARACTER SET utf8mb4**
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '\"'
ESCAPED BY '\"'

Query OK, 75641 rows affected (1.14 sec)
Records: 75641  Deleted: 0  Skipped: 0  Warnings: 0

Документация здесь неверна: https://cloud.google.com/sql/docs/mysql/import-export/importing

  LOAD DATA INFILE ... ***CHARACTER SET 'utf8mb4'***
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '\"'.

1 Ответ

0 голосов
/ 14 января 2019

Решение заключается в установке следующего флага в вашем экземпляре Google Cloud SQL:

character-set-server: utf8mb4

Настройка флагов базы данных

Команда CLI:

gcloud sql instances patch [INSTANCE_NAME] --database-flags character-set-server=utf8mb4

Флаги базы данных перечислены под settings как коллекция databaseFlags:

gcloud sql instances describe [INSTANCE_NAME]

Предупреждение. Любой флаг, не включенный в команду patch, вернется к значению по умолчанию.

...