openswoole / ext-openswoole

Programmatic server for PHP with async IO, coroutines and fibers
https://openswoole.com
Apache License 2.0
808 stars 51 forks source link

PostgreSQL()->fetchAll() should not return false if ((pg_numrows = PQntuples(pg_result)) <= 0) #182

Closed RedChops closed 2 years ago

RedChops commented 2 years ago

Please answer these questions before submitting your issue.

  1. What did you do? If possible, provide a simple script for reproducing the error.

If I run a query which otherwise returns successfully, but does not return rows, fetchAll() will return false. A basic example could be to create a new table, we can define it like:

CREATE TABLE test_empty(
     did    serial,
     name   varchar(40) NOT NULL CHECK (name <> '')
);

Then run $pg->query('SELECT * from test_empty');

  1. What did you expect to see?

I would expect to see an empty array returned, showing that the request was successful but returned an empty set. This command in pgsql returns:

# select * from test_empty;
 did | name
-----+------
(0 rows)
  1. What did you see instead?

false is returned, which across the rest of the extension indicates that there was an error with the command, except $pg->error is null, suggesting that the command was successful. I believe that the conditional mentioned in the title of the ticket is the cause of this, since if that conditional passes (0 rows returned, but otherwise successful), swoole_pgsql_result2array will improperly return FAILURE.

  1. What version of OpenSwoole are you using (show your php --ri openswoole)?
openswoole

Open Swoole => enabled
Author => Open Swoole Group <hello@openswoole.com>
Version => 4.10.0
Built => Mar 11 2022 14:24:47
coroutine => enabled with boost asm context
epoll => enabled
eventfd => enabled
signalfd => enabled
cpu_affinity => enabled
spinlock => enabled
rwlock => enabled
openssl => OpenSSL 1.1.1k  25 Mar 2021
dtls => enabled
pcre => enabled
zlib => 1.2.11
brotli => E16777225/D16777225
mutex_timedlock => enabled
pthread_barrier => enabled
futex => enabled
async_redis => enabled
postgresql => enabled

Directive => Local Value => Master Value
swoole.enable_coroutine => On => On
swoole.enable_library => On => On
swoole.enable_preemptive_scheduler => Off => Off
swoole.display_errors => On => On
swoole.use_shortname => On => On
swoole.unixsock_buffer_size => 8388608 => 8388608
  1. What is your machine environment used (show your uname -a & php -v & gcc -v) ?

uname: Linux 50d1a3fdb76e 5.10.60.1-microsoft-standard-WSL2 #1 SMP Wed Aug 25 23:20:18 UTC 2021 x86_64 GNU/Linux Note: running in a debian-bullseye Docker container

php : PHP 8.1.3 (cli) (built: Mar 11 2022 02:58:22) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.3, Copyright (c) Zend Technologies with Zend OPcache v8.1.3, Copyright (c), by Zend Technologies

gcc is not installed in this container.

RedChops commented 2 years ago

I've been able to temporarily mitigate this issue by using this in my code:

        if (($response = $connection->fetchAll($result)) === false) {
            if (!(in_array($connection->resultStatus, [0, 1, 2]))) {
                throw new Exception($connection->error, $connection->errCode);
            }
            $response = [];
        }

But since Swoole does not package the postgres PQresultStatus enums as constants, I had to look up the numeric values from the postgres source to get an acceptable (but maybe incomplete) list of success integers.

doubaokun commented 2 years ago

Fix these issues at https://github.com/openswoole/swoole-src/pull/187