From f7dd2ceb073932729390a6a7c98523cd4064bfb6 Mon Sep 17 00:00:00 2001 From: codeliner Date: Wed, 10 Jul 2019 00:25:40 +0200 Subject: [PATCH] Do not encode metadata column val --- src/PostgresDocumentStore.php | 32 ++++++++++---- tests/MetadataPostgresDocumentStoreTest.php | 46 +++++++++++++++++++++ 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/PostgresDocumentStore.php b/src/PostgresDocumentStore.php index 6e724f5..3eea1b4 100644 --- a/src/PostgresDocumentStore.php +++ b/src/PostgresDocumentStore.php @@ -566,27 +566,27 @@ private function filterToWhereClause(Filter $filter, $argsCount = 0): array return $this->makeInClause('id', $filter->valList(), $argsCount); case DocumentStore\Filter\AnyOfFilter::class: /** @var DocumentStore\Filter\AnyOfFilter $filter */ - return $this->makeInClause($this->propToJsonPath($filter->prop()), $filter->valList(), $argsCount, true); + return $this->makeInClause($this->propToJsonPath($filter->prop()), $filter->valList(), $argsCount, $this->shouldJsonEncodeVal($filter->prop())); case DocumentStore\Filter\EqFilter::class: /** @var DocumentStore\Filter\EqFilter $filter */ $prop = $this->propToJsonPath($filter->prop()); - return ["$prop = :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount]; + return ["$prop = :a$argsCount", ["a$argsCount" => $this->prepareVal($filter->val(), $filter->prop())], ++$argsCount]; case DocumentStore\Filter\GtFilter::class: /** @var DocumentStore\Filter\GtFilter $filter */ $prop = $this->propToJsonPath($filter->prop()); - return ["$prop > :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount]; + return ["$prop > :a$argsCount", ["a$argsCount" => $this->prepareVal($filter->val(), $filter->prop())], ++$argsCount]; case DocumentStore\Filter\GteFilter::class: /** @var DocumentStore\Filter\GteFilter $filter */ $prop = $this->propToJsonPath($filter->prop()); - return ["$prop >= :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount]; + return ["$prop >= :a$argsCount", ["a$argsCount" => $this->prepareVal($filter->val(), $filter->prop())], ++$argsCount]; case DocumentStore\Filter\LtFilter::class: /** @var DocumentStore\Filter\LtFilter $filter */ $prop = $this->propToJsonPath($filter->prop()); - return ["$prop < :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount]; + return ["$prop < :a$argsCount", ["a$argsCount" => $this->prepareVal($filter->val(), $filter->prop())], ++$argsCount]; case DocumentStore\Filter\LteFilter::class: /** @var DocumentStore\Filter\LteFilter $filter */ $prop = $this->propToJsonPath($filter->prop()); - return ["$prop <= :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount]; + return ["$prop <= :a$argsCount", ["a$argsCount" => $this->prepareVal($filter->val(), $filter->prop())], ++$argsCount]; case DocumentStore\Filter\LikeFilter::class: /** @var DocumentStore\Filter\LikeFilter $filter */ $prop = $this->propToJsonPath($filter->prop()); @@ -614,7 +614,7 @@ private function filterToWhereClause(Filter $filter, $argsCount = 0): array case DocumentStore\Filter\InArrayFilter::class: /** @var DocumentStore\Filter\InArrayFilter $filter */ $prop = $this->propToJsonPath($filter->prop()); - return ["$prop @> :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount]; + return ["$prop @> :a$argsCount", ["a$argsCount" => $this->prepareVal($filter->val(), $filter->prop())], ++$argsCount]; case DocumentStore\Filter\ExistsFilter::class: /** @var DocumentStore\Filter\ExistsFilter $filter */ $prop = $this->propToJsonPath($filter->prop()); @@ -708,6 +708,24 @@ private function indexToSqlCmd(Index $index, string $collectionName): string return $cmd; } + private function prepareVal($value, string $prop) + { + if(!$this->shouldJsonEncodeVal($prop)) { + return $value; + } + + return \json_encode($value); + } + + private function shouldJsonEncodeVal(string $prop): bool + { + if($this->useMetadataColumns && strpos($prop, 'metadata.') === 0) { + return false; + } + + return true; + } + private function getIndexName(Index $index): ?string { if(method_exists($index, 'name')) { diff --git a/tests/MetadataPostgresDocumentStoreTest.php b/tests/MetadataPostgresDocumentStoreTest.php index d4abfe5..402d3fc 100644 --- a/tests/MetadataPostgresDocumentStoreTest.php +++ b/tests/MetadataPostgresDocumentStoreTest.php @@ -315,6 +315,52 @@ public function it_fills_and_queries_metadata_column() $this->assertEquals('v4', $docs[0]['state']['name']); } + /** + * @test + */ + public function it_fills_and_queries_metadata_varchar_column() + { + $collectionName = 'test_col_query_name_meta'; + + $index1 = new MetadataColumnIndex( + FieldIndex::namedIndexForField('meta_field_idx_name', 'metadata.name'), + new Column('name VARCHAR(10)') + ); + + $this->documentStore->addCollection($collectionName, $index1); + + $docId1 = Uuid::uuid4()->toString(); + $docId2 = Uuid::uuid4()->toString(); + $docId3 = Uuid::uuid4()->toString(); + + $this->documentStore->addDoc($collectionName, $docId1, ['state' => ['name' => 'v1'], 'metadata' => ['name' => 'v1']]); + $this->documentStore->addDoc($collectionName, $docId2, ['state' => ['name' => 'v2'], 'metadata' => ['name' => 'v2']]); + $this->documentStore->addDoc($collectionName, $docId3, ['state' => ['name' => 'v3'], 'metadata' => ['name' => 'v3']]); + + $prefix = self::TABLE_PREFIX; + $stmt = "SELECT * FROM $prefix{$collectionName} WHERE name = 'v2';"; + $stmt = $this->connection->prepare($stmt); + $stmt->execute(); + $docs = $stmt->fetchAll(); + + $this->assertCount(1, $docs); + $this->assertEquals($docId2, $docs[0]['id']); + $this->assertEquals(['state' => ['name' => 'v2']], json_decode($docs[0]['doc'], true)); + $this->assertEquals('v2', $docs[0]['name']); + + $docs = iterator_to_array($this->documentStore->filterDocs( + $collectionName, + new GteFilter('metadata.name', 'v2'), + null, + null, + Desc::byProp('metadata.name') + )); + + $this->assertCount(2, $docs); + $this->assertEquals('v3', $docs[0]['state']['name']); + $this->assertEquals('v2', $docs[1]['state']['name']); + } + private function getIndexes(string $collectionName): array { return TestUtil::getIndexes($this->connection, self::TABLE_PREFIX.$collectionName);