0

我正在尝试从 node.js 自动创建数据库并删除 postgres sql 上的表。我编写了一个运行良好的脚本,但它的行为方式很奇怪。让我先在这里发布代码然后解释这个问题。

db.js 文件

      require('dotenv').config()

  const { Pool } = require('pg')
  const isProduction = process.env.NODE_ENV === 'production'

  // don't try to load .env file on Heroku
  if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
  }

  // get the current environment
  var env = process.env.NODE_ENV

  console.log(env);

  // convert to uppercase
  var envString = env.toUpperCase()

  // access the environment variables for this environment
  var DB_USER = process.env['DB_USER_' + envString]
  var DB_PASSWORD = process.env['DB_PASSWORD_' + envString]
  var DB_HOST = process.env['DB_HOST_' + envString]
  var DB_PORT = process.env['DB_PORT_' + envString]
  var DB_DATABASE = process.env['DB_DATABASE_' + envString]

  const connectionString = `postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}`

  const pool = new Pool({
    connectionString: connectionString
  });

  pool.on('connect', () => {
    console.log('connected to the database');
  });

  /**
   * Create Users Table
   */
  const createUsersTable = () => {
    const queryText =
      `CREATE TABLE IF NOT EXISTS users (
          userId SERIAL PRIMARY KEY,
          firstName VARCHAR (50) NOT NULL,
          lastName VARCHAR (50) NOT NULL,
          email VARCHAR (50) NOT NULL,
          password VARCHAR (255) NOT NULL,
          gender VARCHAR(10) check (gender in ('Male', 'Female')),
          jobRole VARCHAR(10) check (jobRole in ('Admin', 'User')),
          department VARCHAR (100) NOT NULL,
          address VARCHAR (100) NOT NULL,
          createdOn TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
          UNIQUE (email)
        )`;

    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
   * Create GIFs Table
   */
  const createGifsTable = () => {
    const queryText =
      `CREATE TABLE IF NOT EXISTS Gifs (
          gifId SERIAL PRIMARY KEY,
          image VARCHAR (50) NOT NULL,
          title VARCHAR (50) NOT NULL,
          flags INTEGER DEFAULT 0,
          userId INTEGER REFERENCES Users(userId) ON DELETE CASCADE,
          createdOn TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
        )`;

    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
   * Create Articles Table
   */
  const createArticlesTable = () => {
    const queryText =
      `CREATE TABLE IF NOT EXISTS Articles (
          articleId SERIAL PRIMARY KEY,
          title VARCHAR (100) NOT NULL,
          article TEXT NOT NULL,
          flags INTEGER DEFAULT 0,
          userId INTEGER REFERENCES Users(userId) ON DELETE CASCADE,
          createdOn TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
        )`;

    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
   * Create Category Table
   */
  const createCategoryTable = () => {
    const queryText =
      `CREATE TABLE IF NOT EXISTS Category (
          categoryId SERIAL PRIMARY KEY,
          category VARCHAR (50) NOT NULL,
          articleId INTEGER REFERENCES Articles(articleId) ON DELETE CASCADE,
          createdOn TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
        )`;

    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Create ArticleComments Table
  */
  const createArticleCommentsTable = () => {
    const queryText =
      `CREATE TABLE IF NOT EXISTS ArticleComments (
          commentId SERIAL PRIMARY KEY,
          comment TEXT NOT NULL,
          flags INTEGER DEFAULT 0,
          articleId INTEGER REFERENCES Articles(articleId) ON DELETE CASCADE,
          createdOn TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
        )`;

    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Create GifComments Table
  */
  const createGifCommentsTable = () => {
    const queryText =
      `CREATE TABLE IF NOT EXISTS GifComments (
          commentId SERIAL PRIMARY KEY,
          comment TEXT NOT NULL,
          flags INTEGER DEFAULT 0,
          gifId INTEGER REFERENCES Gifs(gifId) ON DELETE CASCADE,
          createdOn TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
        )`;

    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Drop Users Table
  */
  const dropUsersTable = () => {
    const queryText = 'DROP TABLE IF EXISTS Users';
    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Drop Gifs Table
  */
  const dropGifsTable = () => {
    const queryText = 'DROP TABLE IF EXISTS Gifs';
    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Drop Articles Table
  */
  const dropArticlesTable = () => {
    const queryText = 'DROP TABLE IF EXISTS Articles';
    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Drop Category Table
  */
  const dropCategoryTable = () => {
    const queryText = 'DROP TABLE IF EXISTS Category';
    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Drop ArticleComments Table
  */
  const dropArticleCommentsTable = () => {
    const queryText = 'DROP TABLE IF EXISTS ArticleComments';
    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Drop GifComments Table
  */
  const dropGifCommentsTable = () => {
    const queryText = 'DROP TABLE IF EXISTS GifComments';
    pool.query(queryText)
      .then((res) => {
        console.log(res);
        pool.end();
      })
      .catch((err) => {
        console.log(err);
        pool.end();
      });
  }

  /**
  * Create All Tables
  */
  const createAllTables = () => {
    createUsersTable();
    createGifsTable();
    createArticlesTable();
    createCategoryTable();
    createArticleCommentsTable();
    createGifCommentsTable();
  }
  /**
  * Drop All Tables
  */
  const dropAllTables = () => {
    dropArticleCommentsTable();
    dropGifCommentsTable();
    dropCategoryTable();
    dropGifsTable();
    dropArticlesTable();
    dropUsersTable();
  }

  pool.on('remove', () => {
    console.log('client removed');
    process.exit(0);
  });


  module.exports = {
    createUsersTable,
    createGifsTable,
    createArticlesTable,
    createCategoryTable,
    createArticleCommentsTable,
    createGifCommentsTable,
    createAllTables,
    dropUsersTable,
    dropGifsTable,
    dropArticlesTable,
    dropCategoryTable,
    dropArticleCommentsTable,
    dropGifCommentsTable,
    dropAllTables
  };

  require('make-runnable');

在这个文件中,我创建了单独的函数来创建和删除数据库表。我在 package.js 上的脚本如下所示:

"scripts": {
  "start": "NODE_ENV=dev nodemon server.js",
  "test": "NODE_ENV=test mocha --exit",
  "dbCreate": "NODE_ENV=dev node -e 'require(\"./db\").createAllTables()'"
}

最后,由于我已db.jscreateAllTables函数中添加了所有单独的创建表命令并将其添加到脚本中,因此我希望在从命令行运行命令时创建表npm run dbCreate

我的问题

当我执行命令npm run dbCreate时,它会创建总共 1 个或 2 个表。当我再次执行时,它会另外创建一个或两个表。因此,对于要创建的所有表,我必须重复执行命令,但我希望一次性完成。当我将createAllTables函数替换为dropAllTables. 有什么我做错了吗?我想在运行自动化测试时使用这个脚本。

4

1 回答 1

0

尽量不要pool.end()在回调中调用。我目前没有时间进行测试,但看起来正在发生的事情是您正在关闭连接然后没有重新打开它,因此由于它们是异步的,您可能能够在第一个解决之前关闭两个命令,但是一旦第一个查询完成,它总是会停止。

于 2019-11-29T08:42:16.807 回答