NodeJS автоматически генерирует модели и запускает миграцию. Ошибка синтаксиса SQL. - PullRequest
5 голосов
/ 09 мая 2019

Я создаю новое приложение NodeJS с MySQL. Мне нужно использовать существующую схему базы данных. У меня есть файл дампа MySQL, который загружается в базу данных (в контейнере Docker). Я пытаюсь автоматически сгенерировать модели и миграции, а затем успешно выполнить их. Я могу генерировать модели и миграции, однако при запуске сгенерированных миграций возникает ошибка синтаксиса SQL.

Вот соответствующие версии:

node10-альпийский

"mysql": "^2.17.1",
"mysql2": "^1.6.5",
"sequelize": "^5.8.5",
"sequelize-auto": "^0.4.29",
"sequelize-auto-migrations": "^1.0.3"

Я использовал модуль sequelize-auto для автоматической генерации моделей. Это работает.

sequelize-auto -o "./models" -d sequelize_auto_test -h localhost -u username -p 5432 -x password -e mysql

Затем я попытался использовать модуль sequelize-auto-migrations, чтобы сгенерировать миграции, а затем запустить их автоматически.

Генерация исходного файла миграции работает.

node ./node_modules/sequelize-auto-migrations/bin/makemigration --name <initial_migration_name>

Однако при выполнении фактической миграции возникает синтаксическая ошибка.

node ./node_modules/sequelize-auto-migrations/bin/runmigration

Это работает для многих таблиц, но затем возникает синтаксическая ошибка.

     code: 'ER_PARSE_ERROR',
     errno: 1064,
     sqlState: '42000',
     sqlMessage:
      'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near \') ENGINE=InnoDB\' at line 1',
     sql: 'CREATE TABLE IF NOT EXISTS `osw` () ENGINE=InnoDB;' },
  sql: 'CREATE TABLE IF NOT EXISTS `osw` () ENGINE=InnoDB;' }

Вот соответствующая модель osw.js (генерируется модулем sequelize-auto):

/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('osw', {
    OSWID: {
      type: DataTypes.INTEGER(10).UNSIGNED,
      allowNull: false,
      primaryKey: true
    },
    IdentificationID: {
      type: DataTypes.INTEGER(10).UNSIGNED,
      allowNull: true,
      references: {
        model: 'itemidentification',
        key: 'IdentificationID'
      }
    },
    ProposedHours: {
      type: DataTypes.DECIMAL,
      allowNull: true
    },
    WorkStartDate: {
      type: DataTypes.DATEONLY,
      allowNull: true
    },
    WorkEndDate: {
      type: DataTypes.DATEONLY,
      allowNull: true
    },
    FormatID: {
      type: DataTypes.INTEGER(10).UNSIGNED,
      allowNull: true,
      references: {
        model: 'formats',
        key: 'FormatID'
      }
    },
    WorkLocationID: {
      type: DataTypes.INTEGER(10).UNSIGNED,
      allowNull: true
    }
  }, {
    tableName: 'osw'
  });
};

Вот соответствующая часть файла дампа mysql:

CREATE TABLE `OSW` (
  `OSWID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `IdentificationID` int(10) unsigned DEFAULT NULL,
  `ProposedHours` decimal(10,2) DEFAULT NULL,
  `WorkStartDate` date DEFAULT NULL,
  `WorkEndDate` date DEFAULT NULL,
  `FormatID` int(10) unsigned DEFAULT NULL,
  `WorkLocationID` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`OSWID`),
  KEY `OSW_FKIndex1` (`IdentificationID`),
  KEY `OSW_Format` (`FormatID`),
  CONSTRAINT `OSW_Format` FOREIGN KEY (`FormatID`) REFERENCES `formats` (`formatid`) ON DELETE SET NULL,
  CONSTRAINT `OSW_Ident` FOREIGN KEY (`IdentificationID`) REFERENCES `itemidentification` (`identificationid`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1147 DEFAULT CHARSET=utf8 PACK_KEYS=0;

ОБНОВЛЕНИЕ: Я думаю, что проблема может быть связана с миграцией, которая была сгенерирована автоматически. Кажется, что в файле миграции отсутствуют определения типов столбцов и полей, поэтому может быть из-за того, что в команде SQL CREATE table отсутствуют имена столбцов. Вот соответствующая часть файла миграции, которая была сгенерирована для таблицы osw:

var migrationCommands = [{
    {
        fn: "createTable",
        params: [
            "osw",
            {

            },
            {}
        ]
    }
];

1 Ответ

2 голосов
/ 30 мая 2019
  • Да, ошибка SQL заключается в том, что в скобках должен быть список столбцов.
  • Да, файл миграции должен содержать столбцы вместо пустых скобок, как будет показано в правильныхфайл ниже в этом ответе.
  • Причиной неудачной миграции, по-видимому, является недавняя версия Sequelize, указанная в вашем package.json.Остальная часть этого ответа объясняет процесс.

Ваш вывод sequelize-auto выглядел нормально, поэтому я попытался воспроизвести только шаг миграции, с помощью:

  1. Запуск sequelize init (не установлен явно, NPM показывал 4.44) в новом каталоге и вставка osw.js в ./models.
  2. Установка соответствующих версий mysql2 и sequelize-auto-migrations, необходимый минимум дляcall node ./node_modules/sequelize-auto-migrations/bin/makemigration --name osw
  3. Это приводит к миграции / 1-osw.js:
'use strict';

var Sequelize = require('sequelize');

/**
 * Actions summary:
 *
 * createTable "osw", deps: [itemidentification, formats]
 *
 **/

var info = {
    "revision": 1,
    "name": "osw",
    "created": "2019-05-30T03:54:19.054Z",
    "comment": ""
};

var migrationCommands = [{
    fn: "createTable",
    params: [
        "osw",
        {
            "OSWID": {
                "type": Sequelize.INTEGER(10).UNSIGNED,
                "field": "OSWID",
                "primaryKey": true,
                "allowNull": false
            },
            "IdentificationID": {
                "type": Sequelize.INTEGER(10).UNSIGNED,
                "field": "IdentificationID",
                "references": {
                    "model": "itemidentification",
                    "key": "IdentificationID"
                },
                "allowNull": true
            },
            "ProposedHours": {
                "type": Sequelize.DECIMAL,
                "field": "ProposedHours",
                "allowNull": true
            },
            "WorkStartDate": {
                "type": Sequelize.DATEONLY,
                "field": "WorkStartDate",
                "allowNull": true
            },
            "WorkEndDate": {
                "type": Sequelize.DATEONLY,
                "field": "WorkEndDate",
                "allowNull": true
            },
            "FormatID": {
                "type": Sequelize.INTEGER(10).UNSIGNED,
                "field": "FormatID",
                "references": {
                    "model": "formats",
                    "key": "FormatID"
                },
                "allowNull": true
            },
            "WorkLocationID": {
                "type": Sequelize.INTEGER(10).UNSIGNED,
                "field": "WorkLocationID",
                "allowNull": true
            },
            "createdAt": {
                "type": Sequelize.DATE,
                "field": "createdAt",
                "allowNull": false
            },
            "updatedAt": {
                "type": Sequelize.DATE,
                "field": "updatedAt",
                "allowNull": false
            }
        },
        {}
    ]
}];

module.exports = {
    pos: 0,
    up: function(queryInterface, Sequelize)
    {
        var index = this.pos;
        return new Promise(function(resolve, reject) {
            function next() {
                if (index < migrationCommands.length)
                {
                    let command = migrationCommands[index];
                    console.log("[#"+index+"] execute: " + command.fn);
                    index++;
                    queryInterface[command.fn].apply(queryInterface, command.params).then(next, reject);
                }
                else
                    resolve();
            }
            next();
        });
    },
    info: info
};

Это решает непосредственную проблему, но не объясняет ее.Я очистил каталог, инициализировал пакет, установил все зависимости и попытался снова сгенерировать миграцию.Это привело к пустой переменной migrationCommands, как вы показали выше.Попытка удалить и переустановить различные пакеты не имела никакого эффекта - я сгенерировал пустой дюжину раз.Удаление sequelize вызвало ошибку, поэтому я начал заново с пустой директории и npm i -s mysql2 sequelize-auto-migrations; sequelize init.Генерация из osw.js снова сработала.

npm показали, что sequelize-auto-migrations снова использует sequelize 4.44.npm i sequelize установлен 5.8.7, и генерация сразу же стала давать сбой .Таким образом, автоматическая миграция sequelize может генерироваться только для вашей модели в зависимости от более ранней версии sequelize.Не знаю, в чем причина.

...