swooletw / laravel-swoole

High performance HTTP server based on Swoole. Speed up your Laravel or Lumen applications.
MIT License
4.04k stars 389 forks source link

MySQL coroutine does not working. #160

Closed damonto closed 5 years ago

damonto commented 5 years ago

Swoole: 4.0.4 PHP: 7.2.12 Lumen: 5.5

I tired switch native-mysql driver to swoole's coroutine mysql driver but it didn't working. Some error have occurred. Details are as follows:

Undefined index: 00 (SQL: select count(*) as aggregate from `call_users` where `email` =  xxx@xxx);

Undefined index: 00 in /projects/pj/vendor/swooletw/laravel-swoole/src/Coroutine/PDOStatement.php:98 Stack trace: #0 

I tried to dump $this->statement->bindKeyMap and get this results:

[
    '00' => 0
]

So I changed

$inputParameters[$numKey] = $this->bindMap[$nameKey];

to

if (isset($this->bindMap[$nameKey])) {
    $inputParameters[$numKey] = $this->bindMap[$nameKey];
}

It's working.

Leon-zzk commented 5 years ago

I also occur to this error, So i commit a "pull request", welcome to talk about it, thank you https://github.com/swooletw/laravel-swoole/pull/161

Leon-zzk commented 5 years ago

Swoole: 4.0.4 PHP: 7.2.12 Lumen: 5.5

I tired switch native-mysql driver to swoole's coroutine mysql driver but it didn't working. Some error have occurred. Details are as follows:

Undefined index: 00 (SQL: select count(*) as aggregate from `call_users` where `email` =  xxx@xxx);

Undefined index: 00 in /projects/pj/vendor/swooletw/laravel-swoole/src/Coroutine/PDOStatement.php:98 Stack trace: #0 

I tried to dump $this->statement->bindKeyMap and get this results:

[
    '00' => 0
]

So I changed

$inputParameters[$numKey] = $this->bindMap[$nameKey];

to

if (isset($this->bindMap[$nameKey])) {
    $inputParameters[$numKey] = $this->bindMap[$nameKey];
}

It's working.

Hi, it still didn't work after i change to "if (isset($this->bindMap[$nameKey])) { $inputParameters[$numKey] = $this->bindMap[$nameKey]; }" when i config database.connections.mysql-coroutine.timezone for env('DB_TIMEZONE', '+8:00'), So i overrides method "configureTimezone" of MySqlConnector, then it worked well, configureTimezone it's likely: if (isset($config['timezone'])) { $connection->prepare('set time_zone=?')->execute([$config['timezone']]); }

lumen.ERROR: PDOException: Unknown or incorrect time zone: '+8?' in /mnt/hgfs/htmls/sapi.rmb.youxinjinrong.com/vendor/swooletw/laravel-swoole/src/Coroutine/PDOStatement.php:111 Stack trace:,

0 /mnt/hgfs/htmls/sapi.rmb.youxinjinrong.com/vendor/illuminate/database/Connectors/MySqlConnector.php(81): SwooleTW\Http\Coroutine\PDOStatement->execute()

damonto commented 5 years ago

@Leon-zzk Hi. I also set DB_TIMEZONE but it's working for me. Can you provide more details? Such as queries.

Leon-zzk commented 5 years ago

@damonto Hi, I found the source bug, there is no matter with DBTIMEZONE, just change the Coroutine\PDO.php line 187 preg, change '/:(\w+)\b/' to '/:([a-zA-Z]\w*?)\b/', because '/:(\w+)\b/' will match "+8:00", so i think change here, then it work well. And also i add your code to confirm it work better.

$statement = preg_replace_callback(
                '/:([a-zA-Z_]\w*?)\b/',
                function ($matches) use (&$i, &$bindKeyMap) {
                    $bindKeyMap[$matches[1]] = $i++;

                    return '?';
                },
                $statement
            );
Leon-zzk commented 5 years ago

@damonto i am also in beijing, 我用的sql代码是 CashUser::on('mysql-coroutine')->insertGetId(['cid'=>89,'name'=>'haha']);,并且也设置了timezone 为env('DB_TIMEZONE', '+8:00'),然后就执行成功,不再报错了

'mysql-coroutine' => [
            'driver' => 'mysql',
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_general_ci',
            'prefix' => env('DB_PREFIX', ''),
            'timezone' => env('DB_TIMEZONE', '+8:00'),
            'strict' => false,
            'read' => [
                'host' => '127.0.0.1',
                'port' => 3306,
                'username' => 'xin',
                'password' => '123456',
                'database' => 'books',
            ],
            'write' => [
                'host' => '127.0.0.1',
                'port' => 3306,
                'username' => 'xin',
                'password' => '123456',
                'database' => 'books1',
            ],
        ],
damonto commented 5 years ago

@Leon-zzk After I changed the regular expression it's work well. Can you submit your changes in Your PR.

Leon-zzk commented 5 years ago

@damonto which brance should i submit my PR, you can try transaction testing likely, please confirm if it work well in your now environment: in my current brance I also change some code and make transaction() worked,

DB::connection('mysql-coroutine')->transaction(function ()use (&$id){
                CashOrder::on('mysql-coroutine')->whereKey(45)->update(['order_num'=>'abcdef1111','cuser_name'=>'zzk']);
                $id=CashUser::on('mysql-coroutine')->insertGetId(['cid'=>89,'name'=>'haha']);
            });

I submit in swooletw:feature/coroutine_feature branch, And issue in https://github.com/swooletw/laravel-swoole/pull/164

damonto commented 5 years ago

@Leon-zzk I'm sorry. I don't know which branch you can submit , But you can ask @albertcht

albertcht commented 5 years ago

Hi @damonto and @damonto ,

Thanks for your report, I'll take a look at this issue seriously this weekend. Any PR should be submitted to develop branch with related tests.

albertcht commented 5 years ago

Sorry for the late reply, I've merged the pull request and it will be merged to master branch as well. Thanks for your report :)

dahuicyh commented 5 years ago

@Leon-zzk 后来怎么修改的 ,才支持的,我用的这个也报 00 index

laraveladmin-cn commented 10 months ago

这里已经支持了协程数据库连接池,可完美的兼容laravel应用 代码文件地址

 use Illuminate\Database\Connectors\ConnectionFactory;
        $this->app->singleton(ConnectionFactory::class, function ($app) {
            return new \App\Swoole\Coroutine\Database\ConnectionFactory($app);
        });
        $this->app->alias(ConnectionFactory::class,'db.factory');