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

Handling Postgres Error Message To Perform Correct Query

我正在使用 pgnode.js。当用户使用 auth0 小部件登录时,我将电子邮件传递给它 returns 并检查我的数据库以查看该用户是否存在。如果用户不存在,我将把它们插入到数据库中。我已经设法通过一个函数的 hack 工作来完成这项工作,但我希望能得到一些帮助来解决这个问题。

我面临的问题。

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

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

    req.body.email;其实就是myemail@example.com

Returns这个错误,

column "myemail" does not exist

尽管

myemail@example.com

确实存在。

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

    重复键值违反唯一约束"uk_user_email"

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

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)
            }); 
        } 

对于 #1,问题是您没有引用您的输入值。因为(我假设)你可能不想担心引用/转义/等等你自己的价值观,我会考虑使用 parameterized queries。这将有助于保护您免受 sql 注入(并且您当前的代码很容易受到这种影响)。

对于 #2,它实际上 "throw" 不是那个错误。该方法是异步的,并将错误提供给回调。如果你想 运行 查询 "in order",你需要做这样的事情:

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();
  });
});

注意这些调用是如何相互嵌入 "inside" 的(特别是在回调内部)。

您需要用 ' 包裹您的值以使其成为字符串。如果没有字符串换行,它将在列之间进行比较。应该是:

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=";
        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', ,'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)
    });
}