From fa224739cea7a2ab2f5464083d799c1a626bcf11 Mon Sep 17 00:00:00 2001 From: yuzhuang Date: Fri, 10 Nov 2023 22:33:33 +0800 Subject: [PATCH] [10.x] Fix Postgres cache store failed to put in db transaction --- src/Illuminate/Cache/DatabaseStore.php | 4 ++++ tests/Cache/CacheDatabaseStoreTest.php | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/Illuminate/Cache/DatabaseStore.php b/src/Illuminate/Cache/DatabaseStore.php index 19c4ccefe431..e2a6d7306106 100755 --- a/src/Illuminate/Cache/DatabaseStore.php +++ b/src/Illuminate/Cache/DatabaseStore.php @@ -137,6 +137,10 @@ public function put($key, $value, $seconds) $value = $this->serialize($value); $expiration = $this->getTime() + $seconds; + if ($this->connection instanceof PostgresConnection && $this->connection->transactionLevel() > 0) { + return $this->table()->upsert(compact('key', 'value', 'expiration'), 'key') > 0; + } + try { return $this->table()->insert(compact('key', 'value', 'expiration')); } catch (Exception) { diff --git a/tests/Cache/CacheDatabaseStoreTest.php b/tests/Cache/CacheDatabaseStoreTest.php index ac98021eb87c..b71e4fb36124 100755 --- a/tests/Cache/CacheDatabaseStoreTest.php +++ b/tests/Cache/CacheDatabaseStoreTest.php @@ -91,10 +91,24 @@ public function testValueIsUpdatedWhenInsertThrowsException() $this->assertTrue($result); } + public function testValueIsUpsertDuringTransactionOnPostgres() + { + $store = $this->getMockBuilder(DatabaseStore::class)->onlyMethods(['getTime'])->setConstructorArgs($this->getPostgresMocks())->getMock(); + $table = m::mock(stdClass::class); + $store->getConnection()->shouldReceive('transactionLevel')->once()->andReturn(1); + $store->getConnection()->shouldReceive('table')->once()->with('table')->andReturn($table); + $store->expects($this->once())->method('getTime')->willReturn(1); + $table->shouldReceive('upsert')->once()->with(['key' => 'prefixfoo', 'value' => base64_encode(serialize("\0")), 'expiration' => 61], 'key')->andReturnTrue(); + + $result = $store->put('foo', "\0", 60); + $this->assertTrue($result); + } + public function testValueIsInsertedOnPostgres() { $store = $this->getMockBuilder(DatabaseStore::class)->onlyMethods(['getTime'])->setConstructorArgs($this->getPostgresMocks())->getMock(); $table = m::mock(stdClass::class); + $store->getConnection()->shouldReceive('transactionLevel')->once()->andReturn(0); $store->getConnection()->shouldReceive('table')->once()->with('table')->andReturn($table); $store->expects($this->once())->method('getTime')->willReturn(1); $table->shouldReceive('insert')->once()->with(['key' => 'prefixfoo', 'value' => base64_encode(serialize("\0")), 'expiration' => 61])->andReturnTrue();