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

Node.js 处理Postgres错误消息以执行正确的查询,node.js,postgresql,angular,node-postgres,Node.js,Postgresql,Angular,Node Postgres,我正在使用pg和node.js。当用户使用auth0小部件登录时,我正在传递它返回的电子邮件,并检查我的数据库以查看该用户是否存在。如果用户不存在,我将把他们插入数据库。我已经设法让这与一个函数的黑客工作,但我会感谢一些帮助熨烫出来 我面临的问题 在检查数据库中的电子邮件时,它并不是在检查整个电子邮件地址 var emailCheck=从public.user中选择id,其中email=+req.body.email req.body.email;实际上是myemail@example.com

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

我面临的问题

在检查数据库中的电子邮件时,它并不是在检查整个电子邮件地址

var emailCheck=从public.user中选择id,其中email=+req.body.email

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

返回此错误

column "myemail" does not exist
即使

myemail@example.com
确实存在

不管它抛出什么错误,它都会继续插入电子邮件地址。如果不存在,则将其插入。因为电子邮件上有一个唯一的密钥,所以会抛出一个错误

重复的键值违反了唯一约束uk\u用户\u电子邮件

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

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,问题是您没有引用输入值。因为我假设您可能不想担心引用/转义/等您自己的值,所以我会考虑使用。这将有助于防止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();
  });
});

请注意调用是如何嵌入在回调中的。具体来说,对于1,问题是您没有引用输入值。因为我假设您可能不想担心引用/转义/等您自己的值,所以我会考虑使用。这将有助于防止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();
  });
});

请注意这些调用是如何嵌入到回调中的,特别是。

您需要用“将值包装为字符串”。如果没有字符串换行,它将在列之间进行比较。应该是:

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

您需要使用“将值包装为字符串”。如果没有字符串换行,它将在列之间进行比较。应该是:

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

嘿,非常感谢!这让我很痛苦。我不明白你说的第一是什么意思。它可以插入完整的电子邮件。为什么不检查整个电子邮件?我不明白检查它是否存在和插入它之间有什么区别。哦,在你的检查查询中,你没有在你的电子邮件周围加上单引号,所以postgres的查询解析器出错了。这就是第一个错误的来源。嘿,非常感谢!这让我很痛苦。我不明白你说的第一是什么意思。它可以插入完整的电子邮件。为什么不检查整个电子邮件?我不明白检查它是否存在和插入它之间有什么区别。哦,在你的检查查询中,你没有在你的电子邮件周围加上单引号,所以postgres的查询解析器出错了。这就是第一个错误的来源。我的另一个2美分,最好使用prepared语句而不是concat查询字符串,以获得更好的安全性和控制,如自动转义和数据类型检测。参考我上面更新的答案,如果我要添加5个值,请您向我解释$1,它是否知道$1是第一个变量项,如果有第二个变量项,请使用$2?如果不是这样的话,那该怎么做呢?我的另一个2美分,总是最好使用prepared语句而不是concat查询字符串,以获得更好的安全性和控制,比如自动转义和数据类型检测。参考我上面更新的答案,如果我要添加5个值,请您向我解释$1,它是否知道$1是第一个变量项,如果有第二个变量项,请使用$2?如果不是这样的话,那怎么办?