duanbi1983 2018-09-12 01:05
浏览 160

当准备好的查询省略NOT NULL字段时,PostgreSQL PHP PDO执行挂起

Using PostgreSQL 9.6 and PHP 7.2, I am creating a PDO connection, preparing an INSERT query, binding the parameters, then executing the prepared query. I have ATTR_ERRMODE set to ERRMODE_EXCEPTION, and in fact can cause exceptions to be thrown by the execute if, for example, the prepared query has 4 parameters, but I’ve only bound 3.

But if my prepared query doesn’t include a field with a NOT NULL constraint, then the execute hangs for maybe 20 seconds, then the browser displays “the connection was reset”. The Postgres log says:

ERROR:  null value in column "fullname" violates not-null constraint
DETAIL:  Failing row contains (345, fredf, fredf@bedrock.net, yabadabadoo, null, Bedrock, none, user).
STATEMENT:  INSERT INTO users (username, password, location, description, email, role) VALUES ($1, $2, $3, $4, $5, $6)
LOG:  could not receive data from client: An existing connection was forcibly closed by the remote host.

These 4 log entries repeat a total of 10 times.

I understand this situation is really a programming issue -- the query should be consistent with the requirements of the database design. But I’d really like to coax the Postgres PDO driver into telling me what the error was, rather than have to go dig through logs.


Sample code

/*

Sample code to demonstrate failure of prepared query execute()
to throw an exception when the prepared query omits a field
with a NOT NULL constraint.

CREATE TABLE users (
  id                SERIAL PRIMARY KEY,
  username      varchar(50) NOT NULL,
  email           varchar(100) NOT NULL,
  password      varchar(255) NOT NULL,
  fullname      varchar(100) NOT NULL,
  location      varchar(100) NOT NULL,
  description text NOT NULL,
  role            varchar(50) NOT NULL DEFAULT ''
);

*/
    $host   = "localhost";  
    $user   = "postgres";  
    $pass   = "password";  
    $dbname = "database";  
    /**
     * Initialize the PDO connection. 
     */
        $dsn = 'pgsql:host=' . $host . ';dbname=' . $dbname;
        $options = [
            PDO::ATTR_PERSISTENT => true,  
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION  
            ]; 
        try {  
            $handler = new PDO($dsn, $user, $pass, $options);  
        } catch (PDOException $e) {  
            echo $e->getMessage();
            die();  
        } 

     /**
      * Demonstrate failure of execute() to return an error or throw an exception
      * Error condition omits the fullname field from the INSERT query, which has a 
      * "not null" constraint.
      */
        $demonstrateProblem = 1;

        $badQuery = "INSERT INTO users (username, password, location, description, email, role) " . 
                    "VALUES (:username, :password, :location, :description, :email, :role)";

        $goodQuery = "INSERT INTO users (username, password, fullname, location, description, email, role) " . 
                    "VALUES (:username, :password, :fullname, :location, :description, :email, :role)";

        if ($demonstrateProblem == 1) {
            $query = $badQuery;
        } else  {
            $query = $goodQuery;
        }

        $stmt = $handler->prepare($query);  
        if (!$stmt) {
            echo "Error in prepare, errorInfo():<br>";
            print_r($handler->errorInfo());
        }
    /**
     * Bind the variables
     */
        $username   = "fredf";
        $password   = "yabadabadoo";
        $fullname   = "Fred Flintstone";
        $location   = "Bedrock";
        $description = "none";
        $email      = "fredf@bedrock.net";
        $role       = "user";

        $stmt->bindParam(':username', $username);
        $stmt->bindParam(':password', $password);
        if ($demonstrateProblem == 0) {
            $stmt->bindParam(':fullname', $fullname);
        } else {
            // nothing to do, :fullname is not in the prepared query!
        }
        $stmt->bindParam(':location', $location);
        $stmt->bindParam(':description', $description);
        $stmt->bindParam(':email', $email);
        $stmt->bindParam(':role', $role);
    /**
     * Execute a prepared statement.
     */
        echo "Executing prepared query...<br>";
        try {
            $res = $stmt->execute(); // <-- this statement hangs when the query prepare is bad.
            if ($res) {
                echo "execute returns true<br> ";
            } else {
                echo "execute returns false<br> ";               
            }
        } catch (PDOException $e) {  
            echo "execute error " . $e->getMessage();  // <-- this never appears
        }

PostgreSQL log (sequence repeats 10 times)

 ERROR:  null value in column "fullname" violates not-null constraint
 DETAIL:  Failing row contains (345, fredf, fredf@bedrock.net, yabadabadoo, null, Bedrock, none, user).
 STATEMENT:  INSERT INTO users (username, password, location, description, email, role) VALUES ($1, $2, $3, $4, $5, $6)
 LOG:  could not receive data from client: An existing connection was forcibly closed by the remote host.
  • 写回答

3条回答 默认 最新

  • dougu1952 2018-09-12 01:53
    关注

    Well, you're trying to add data with NULL value for field with NOT NULL constraint on it. You either need to define default value in the Postgresql for "fullname" column, or make it NULL-able.

    评论

报告相同问题?

悬赏问题

  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器