处理Postgres错误消息以执行正确的查询

时间:2016-11-24 00:17:08

标签: node.js postgresql angular node-postgres

我正在使用pgnode.js。当用户使用auth0小部件登录时,我将传递它返回的电子邮件并检查我的数据库以查看用户是否存在。如果用户不存在,我将它们插入数据库。我已经设法让这个工作与一个功能的黑客工作,但我会感谢一些帮助熨平它。

我面临的问题。

  1. 在检查数据库中的电子邮件时,它没有检查整个电子邮件地址。

    var emailCheck = "SELECT id from public.user WHERE email=" + req.body.email;

    req.body.email;实际上是myemail@example.com

  2. 返回此错误,

    column "myemail" does not exist
    

    即使

    myemail@example.com
    

    确实存在。

    1. 无论发生什么错误,它都会继续插入电子邮件地址。如果它不存在则插入它。由于电子邮件中有唯一键,因此会抛出错误

      重复键值违反了唯一约束“uk_user_email”

    2. 所以要解决这个问题,为什么在@符号后没有检查?我应该遵循什么逻辑来更改此函数以运行第一个查询,如果第一个查询找不到相关的电子邮件地址,则只运行第二个查询?

      checkRegister: function(req, res) {
                  pool.connect(function(err, client, done) {
                      if (err) {
                          return console.error('error fetching client from pool', err);
                      } connection
                      var emailCheck = "SELECT id from public.user WHERE email=" + req.body.email;
                      var emailInsert = "insert into public.user (user_auth_level,email,account_locked,contract) " +
                          "values ('1','" + req.body.email + "','false','false')"
                      client.query(emailCheck, function(err, result) {
                          if (err) {
                              return console.error(err.message);
                          }
      
                      });
                      client.query(emailInsert, function(err, result) {
                          if (err) {
                              return console.error(err.message);
                          }
      
                      });
                      done(); 
                  });
                  pool.on('error', function(err, client) {
                      console.error('idle client error', err.message, err.stack)
                  }); 
              } 
      

2 个答案:

答案 0 :(得分:3)

你需要用'来包装你的价值。使它成为字符串。没有字符串换行,它将在列之间进行比较。它应该是:

var yourQuery = "SELECT id from public.user WHERE email=" + req.body.email; // SELECT id from public.user WHERE email=myemail@example.com
var correntQuery = "SELECT id from public.user WHERE email='" + req.body.email + "'"; // SELECT id from public.user WHERE email='myemail@example.com'

Nodejs是同步的,您需要使用回调或承诺链接您的代码,如下所示:

checkRegister: function (req, res) {
    pool.connect(function (err, client, done) {
        if (err) {
            console.error(err);
            // should return response error like 
            return res.status(500).send();
        }
        var emailCheck = "SELECT id from public.user WHERE email=$1";
        client.query(emailCheck, [req.body.email], function (err, result) {
            if (err) {
                console.error(err);
                res.status(500).send();
                return done(); // always close connection
            }
            if (result.rowCount > 0) {
                let user = result.rows[0]
                // return your user
                return done(); // always close connection
            } else {
                var emailInsert = "insert into public.user (user_auth_level, email, account_locked, contract) " +
                    "values ('1', $1,'false','false') RETURNING *"
                client.query(emailInsert, [req.body.email], function (err, result) {
                    if (err) {
                        console.error(err);
                        res.status(500).send();
                        return done(); // always close connection
                    } else {
                        if (result.rowCount > 0) {
                            let user = result.rows[0]
                            // return your user
                            return done(); // always close connection
                        }
                    }

                });
            }
        })
    })
    pool.on('error', function (err, client) {
        console.error('idle client error', err.message, err.stack)
    });
} 

答案 1 :(得分:1)

对于#1,问题是您没有引用输入值。由于(我假设)你可能不想担心引用/转义/等你自己的值,我会考虑使用parameterized queries。这将有助于保护您免受SQL注入(并且您当前的代码非常暴露于此)。

对于#2,它实际上并没有“抛出”该错误。该方法是异步的,并为回调提供错误。如果您想“按顺序”运行查询,则需要执行以下操作:

client.query(emailCheck, function(err, result) {
  if (err) {
    // should probably do `return done(err);` here
    return console.error(err.message);
  }
  client.query(emailInsert, function(err, result) {
    if (err) {
      // same thing - probably need done(err) in here
      return console.error(err.message);
    }
    return done();
  });
});

注意调用是如何嵌入彼此“内部”的(特别是在回调内部)。