Ошибка Knex при загрузке SQL FIle - синтаксическая ошибка в или около "undefined" - PullRequest
0 голосов
/ 16 апреля 2020

Я уверен, что это простая проблема, но я застрял, и доктор Google не помогает.

В основном я пытаюсь загрузить файлы схемы SQL в процессе миграции с использованием Knex в Node. Файлы SQL напрямую из PGAdmin, никаких данных, только схема.

По сути, я загружаю файлы SQL из файловой системы и knex.raw() применяю их. Я вижу, что SQL загружается нормально, он выплевывает в консоль.

Мой метод миграции выглядит так:

exports.up = knex => {
    const schemaFilePath = path.join(__dirname, "../db/schema");
    const schemaFiles = fs.readdirSync(schemaFilePath);
    let sql;
    schemaFiles.forEach(async file => {
        sql += fs.readFileSync(path.join(schemaFilePath, file), "utf8");
    });
    return knex.raw(sql);
};

Есть несколько SQL файлов, загруженных из этой схемы Каталог, который выглядит следующим образом. (с закомментированными строками и т. д. c)

-- Table: public.roles

-- DROP TABLE public.roles;

CREATE TABLE public.roles
(
    _id uuid NOT NULL DEFAULT uuid_generate_v4(),
    "displayName" citext COLLATE pg_catalog."default",
    "createdAt" timestamp with time zone NOT NULL,
    "updatedAt" timestamp with time zone NOT NULL,
    "deletedAt" timestamp with time zone,
    "_fullTextSearch" citext COLLATE pg_catalog."default",
    system boolean DEFAULT false,
....

Я получаю ошибку:

    ON public.validations USING btree
    ("updatedAt" ASC NULLS LAST)
    TABLESPACE pg_default;

 - syntax error at or near "undefined"
error: syntax error at or near "undefined"
at Connection.parseE (/xxx/node_modules/pg/lib/connection.js:604:13)

Это не тот конкретный файл, как будто я просто удаляю этот файл, я все еще получаю та же ошибка, просто в другом файле.

Прокручивая выведенные журналы, все SQL выглядит нормально для меня.

Iv проверен на наличие плохих символов, пробелы и т. д. c. Я не знаю где.

Надеюсь, я просто что-то здесь не так делаю.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Ненавижу отвечать на свой вопрос, но я поняла, что происходит. Спасибо всем, кто ответил.

У всех, кто пытался сделать то же самое, было несколько проблем с этим кодом.

Сначала ошибка о том, что "undefined" была вызвана

let sql;
sql += fs.readFileSync(path.join(schemaFilePath, file), "utf8");

В самом начале оператора SQL было сгенерировано «неопределенное». Решено

let sql = "";

Далее я столкнулся с проблемой плохих персонажей, которые на этот раз были совершенно невидимыми и найти их было сложно. Я смог найти их только путем записи содержимого строки обратно в файл, в котором я увидел кучу недопустимых символов, которые, как мне кажется, не совместимы с UTF-8.

Это было из-за того, что скрытые файлы были удалены из файловой системы. ie

    schemaFiles.forEach(file => {
        sql += fs.readFileSync(path.join(schemaFilePath, file), "utf8");
    });

Как и в случае с Ma c, оказывается, что он также загружал эти надоедливые файлы .DS_Store, которые вставляли двоичный мусор, хотя это не было видно на экране, только после записи содержимого обратно в плоский файл.

Я собирался попробовать psql загрузить его. psql дал мне лучшее сообщение об ошибке.

Решено это путем фильтрации только. sql files

     schemaFiles.forEach(file => {
        if (file.substr(file.length - 4) === ".sql") {
         code ....
        }
     })

Наконец, у меня были проблемы с загрузкой файлов схемы из-за CONSTRAINTS и таблиц отсутствует в схеме, поэтому я использую pg_dump для получения допустимого файла схемы, исключая таблицы миграции knex

pg_dump --schema-only --exclude-table=knex* > db/schema.sql

Теперь файл миграции по сути состоит из одной строки

return knex.raw(fs.readFileSync(path.join(__dirname, "../db/schema.sql"), "utf8"));

Надеюсь, это поможет любому, кто застрянет

1 голос
/ 17 апреля 2020

Поскольку pg@7 должно выполняться выполнение нескольких операторов с помощью knex raw. Так что есть небольшое изменение, что это на самом деле может работать, но я никогда не проверял это сам.

Если вы запускаете эти файлы SQL по одному, это работает лучше?

Вы уверены, что concat не испортил их?

Это происходит всегда после определенного количества SQL, может быть, есть ограничение для максимального размера запроса?

Я всегда использовал инструменты командной строки для сохранения / восстановления дампов БД.

Вероятно, можно запустить эти инструменты в файле миграции knex, а затем позволить системе миграции knex отметить, что миграция уже используется.

Я использовал этот вид функций для сохранения / восстановления состояний базы данных из кода узла (обычно для сохранения состояний системы между различными настройками теста e2e, чтобы иметь возможность запустить запуск e2e с середины выполнения):

 async dump(dumpFileName, user, password, database, host) {
    return new Promise((resolve, reject) => {
      const cmd = [
        `export PGPASSWORD=${password};`,
        `pg_dump -a -O -x -F c`,
        `-f '${dumpFileName}'`,
        `-d ${database}`,
        `-h ${host}`,
        `-p 5432`,
        `-U ${user}`
      ].join(' ');

      shelljs.rm('-f', dumpFileName);
      shelljs.exec(cmd, (code, stdout, stderr) => {
        console.log(`Command ready: ${cmd}, with exit code: ${code}`);
        if (code === 0) {
          resolve(stdout);
        } else {
          reject(new Error(stderr));
        }
      });
    });
  }

  async restore(dumpFileName, user, password, database, host) {
    return new Promise((resolve, reject) => {
      const cmd = [
        `export PGPASSWORD=${password};`,
        `cat '${dumpFileName}' | `,
        `pg_restore -a -O -x -F c`,
        `-d ${database}`,
        `-h ${host}`,
        `-p 5432`,
        `-U ${user}`,
        `--disable-triggers"`
      ].join(' ');

      shelljs.exec(cmd, (code, stdout, stderr) => {
        console.log(`Command ready: ${cmd}, with exit code: ${code}`);
        if (code === 0) {
          resolve(stdout);
        } else {
          reject(new Error(stderr));
        }
      });
    });
  }

Не идеальное решение, но может сработать для кого-то ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...