Skip to content

Commit df526cc

Browse files
authored
PCBC-888 handle query context changes (#68)
* Added Collection query index manaager * small fixes * removed commented line * append package.xml * Adding collection index manager test * lint + change error message
1 parent 6f82355 commit df526cc

14 files changed

+858
-0
lines changed

Couchbase/Collection.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use Couchbase\Exception\InvalidArgumentException;
2929
use Couchbase\Exception\TimeoutException;
3030
use Couchbase\Exception\UnsupportedOperationException;
31+
use Couchbase\Management\CollectionQueryIndexManager;
3132
use DateTimeInterface;
3233

3334
/**
@@ -623,4 +624,15 @@ public function binary(): BinaryCollection
623624
{
624625
return new BinaryCollection($this->name, $this->scopeName, $this->bucketName, $this->core);
625626
}
627+
628+
/**
629+
* Creates a new manager object for managing N1QL query indexes at the collection level
630+
*
631+
* @return CollectionQueryIndexManager
632+
* @since 4.1.2
633+
*/
634+
public function queryIndexes(): CollectionQueryIndexManager
635+
{
636+
return new CollectionQueryIndexManager($this->name, $this->scopeName, $this->bucketName, $this->core);
637+
}
626638
}

Couchbase/Management/BuildQueryIndexesOptions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static function build(): BuildQueryIndexesOptions
4040
/**
4141
* @param string $scopeName
4242
*
43+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
4344
* @return BuildQueryIndexesOptions
4445
* @since 4.0.0
4546
*/
@@ -52,6 +53,7 @@ public function scopeName(string $scopeName): BuildQueryIndexesOptions
5253
/**
5354
* @param string $collectionName
5455
*
56+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
5557
* @return BuildQueryIndexesOptions
5658
* @since 4.0.0
5759
*/
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
<?php
2+
3+
/**
4+
* Copyright 2014-Present Couchbase, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
namespace Couchbase\Management;
20+
21+
use Couchbase\Exception\InvalidArgumentException;
22+
use Couchbase\Exception\UnambiguousTimeoutException;
23+
use Couchbase\Extension;
24+
25+
class CollectionQueryIndexManager
26+
{
27+
private string $collectionName;
28+
private string $scopeName;
29+
private string $bucketName;
30+
/**
31+
* @var resource
32+
*/
33+
private $core;
34+
35+
36+
/**
37+
* @param string $collectionName
38+
* @param string $scopeName
39+
* @param string $bucketName
40+
* @param $core
41+
*
42+
* @internal
43+
* @since 4.1.2
44+
*/
45+
public function __construct(string $collectionName, string $scopeName, string $bucketName, $core)
46+
{
47+
$this->collectionName = $collectionName;
48+
$this->scopeName = $scopeName;
49+
$this->bucketName = $bucketName;
50+
$this->core = $core;
51+
}
52+
53+
/**
54+
* Fetches all indexes from the server.
55+
*
56+
* @param GetAllQueryIndexesOptions|null $options
57+
*
58+
* @return array
59+
* @throws InvalidArgumentException
60+
* @since 4.1.2
61+
*/
62+
public function getAllIndexes(GetAllQueryIndexesOptions $options = null): array
63+
{
64+
$exported = GetAllQueryIndexesOptions::export($options);
65+
$this->checkOptions($exported);
66+
$responses = Extension\collectionQueryIndexGetAll($this->core, $this->bucketName, $this->scopeName, $this->collectionName, $exported);
67+
return array_map(
68+
function (array $response) {
69+
return new QueryIndex($response);
70+
},
71+
$responses
72+
);
73+
}
74+
75+
/**
76+
* Creates a new index
77+
*
78+
* @param string $indexName
79+
* @param array $fields
80+
* @param CreateQueryIndexOptions|null $options
81+
*
82+
* @throws InvalidArgumentException
83+
* @since 4.1.2
84+
*/
85+
public function createIndex(string $indexName, array $fields, CreateQueryIndexOptions $options = null)
86+
{
87+
$exported = CreateQueryIndexOptions::export($options);
88+
$this->checkOptions($exported);
89+
Extension\collectionQueryIndexCreate($this->core, $this->bucketName, $this->scopeName, $this->collectionName, $indexName, $fields, $exported);
90+
}
91+
92+
/**
93+
* Creates a new primary index
94+
*
95+
* @param CreateQueryPrimaryIndexOptions|null $options
96+
*
97+
* @throws InvalidArgumentException
98+
* @since 4.1.2
99+
*/
100+
public function createPrimaryIndex(CreateQueryPrimaryIndexOptions $options = null)
101+
{
102+
$exported = CreateQueryPrimaryIndexOptions::export($options);
103+
$this->checkOptions($exported);
104+
Extension\collectionQueryIndexCreatePrimary($this->core, $this->bucketName, $this->scopeName, $this->collectionName, $exported);
105+
}
106+
107+
/**
108+
* Drops an index
109+
*
110+
* @param string $indexName
111+
* @param DropQueryIndexOptions|null $options
112+
*
113+
* @throws InvalidArgumentException
114+
* @since 4.1.2
115+
*/
116+
public function dropIndex(string $indexName, DropQueryIndexOptions $options = null)
117+
{
118+
$exported = DropQueryIndexOptions::export($options);
119+
$this->checkOptions($exported);
120+
Extension\collectionQueryIndexDrop($this->core, $this->bucketName, $this->scopeName, $this->collectionName, $indexName, $exported);
121+
}
122+
123+
/**
124+
* Drops a primary index
125+
*
126+
* @param DropQueryPrimaryIndexOptions|null $options
127+
*
128+
* @throws InvalidArgumentException
129+
* @since 4.1.2
130+
*/
131+
public function dropPrimaryIndex(DropQueryPrimaryIndexOptions $options = null)
132+
{
133+
$exported = DropQueryPrimaryIndexOptions::export($options);
134+
$this->checkOptions($exported);
135+
Extension\collectionQueryIndexDropPrimary($this->core, $this->bucketName, $this->scopeName, $this->collectionName, $exported);
136+
}
137+
138+
/**
139+
* Build Deferred builds all indexes which are currently in deferred state.
140+
*
141+
* @param BuildQueryIndexesOptions|null $options
142+
*
143+
* @throws InvalidArgumentException
144+
* @since 4.1.2
145+
*/
146+
public function buildDeferredIndexes(BuildQueryIndexesOptions $options = null)
147+
{
148+
$exported = BuildQueryIndexesOptions::export($options);
149+
$this->checkOptions($exported);
150+
Extension\collectionQueryIndexBuildDeferred($this->core, $this->bucketName, $this->scopeName, $this->collectionName, $exported);
151+
}
152+
153+
/**
154+
* Watch polls indexes until they are online.
155+
*
156+
* @param array $indexNames
157+
* @param int $timeoutMilliseconds
158+
* @param WatchQueryIndexesOptions|null $options
159+
*
160+
* @throws UnambiguousTimeoutException|InvalidArgumentException
161+
* @since 4.1.2
162+
*/
163+
public function watchIndexes(array $indexNames, int $timeoutMilliseconds, WatchQueryIndexesOptions $options = null)
164+
{
165+
$exported = WatchQueryIndexesOptions::export($options);
166+
$this->checkOptions($exported);
167+
if (array_key_exists("watchPrimary", $exported) && $exported["watchPrimary"]) {
168+
$indexNames [] = "#primary";
169+
}
170+
$deadline = (int)(microtime(true) * 1000) + $timeoutMilliseconds;
171+
172+
while (true) {
173+
$now = (int)(microtime(true) * 1000);
174+
if ($now >= $deadline) {
175+
throw new UnambiguousTimeoutException(
176+
sprintf(
177+
"Failed to find all indexes online within the allotted time (%dms)",
178+
$timeoutMilliseconds
179+
)
180+
);
181+
}
182+
$options = GetAllQueryIndexesOptions::build()->timeout($deadline - $now);
183+
$foundIndexes = $this->getAllIndexes($options);
184+
$onlineIndexes = [];
185+
/**
186+
* @var QueryIndex $index
187+
*/
188+
foreach ($foundIndexes as $index) {
189+
if ($index->state() == "online") {
190+
$onlineIndexes[$index->name()] = true;
191+
}
192+
}
193+
$allOnline = true;
194+
/**
195+
* @var string $name
196+
*/
197+
foreach ($indexNames as $name) {
198+
if (!array_key_exists($name, $onlineIndexes)) {
199+
$allOnline = false;
200+
break;
201+
}
202+
}
203+
if ($allOnline) {
204+
break;
205+
}
206+
207+
usleep(100_000); /* wait for 100ms */
208+
}
209+
}
210+
211+
/**
212+
* @throws InvalidArgumentException
213+
*/
214+
private function checkOptions(array $exportedOpts)
215+
{
216+
if (isset($exportedOpts['scopeName']) || isset($exportedOpts['collectionName'])) {
217+
throw new InvalidArgumentException("Scope and Collection options cannot be set when using the Query Index Manager at the collection level");
218+
}
219+
}
220+
}

Couchbase/Management/CreateQueryIndexOptions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public static function build(): CreateQueryIndexOptions
4444
/**
4545
* @param string $scopeName
4646
*
47+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
4748
* @return CreateQueryIndexOptions
4849
* @since 4.0.0
4950
*/
@@ -56,6 +57,7 @@ public function scopeName(string $scopeName): CreateQueryIndexOptions
5657
/**
5758
* @param string $collectionName
5859
*
60+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
5961
* @return CreateQueryIndexOptions
6062
* @since 4.0.0
6163
*/

Couchbase/Management/CreateQueryPrimaryIndexOptions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public static function build(): CreateQueryPrimaryIndexOptions
4444
/**
4545
* @param string $scopeName
4646
*
47+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
4748
* @return CreateQueryPrimaryIndexOptions
4849
* @since 4.0.0
4950
*/
@@ -56,6 +57,7 @@ public function scopeName(string $scopeName): CreateQueryPrimaryIndexOptions
5657
/**
5758
* @param string $collectionName
5859
*
60+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
5961
* @return CreateQueryPrimaryIndexOptions
6062
* @since 4.0.0
6163
*/

Couchbase/Management/DropQueryIndexOptions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public static function build(): DropQueryIndexOptions
4141
/**
4242
* @param string $scopeName
4343
*
44+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
4445
* @return DropQueryIndexOptions
4546
* @since 4.0.0
4647
*/
@@ -53,6 +54,7 @@ public function scopeName(string $scopeName): DropQueryIndexOptions
5354
/**
5455
* @param string $collectionName
5556
*
57+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
5658
* @return DropQueryIndexOptions
5759
* @since 4.0.0
5860
*/

Couchbase/Management/DropQueryPrimaryIndexOptions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public static function build(): DropQueryPrimaryIndexOptions
4242
/**
4343
* @param string $scopeName
4444
*
45+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
4546
* @return DropQueryPrimaryIndexOptions
4647
* @since 4.0.0
4748
*/
@@ -54,6 +55,7 @@ public function scopeName(string $scopeName): DropQueryPrimaryIndexOptions
5455
/**
5556
* @param string $collectionName
5657
*
58+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
5759
* @return DropQueryPrimaryIndexOptions
5860
* @since 4.0.0
5961
*/

Couchbase/Management/GetAllQueryIndexesOptions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static function build(): GetAllQueryIndexesOptions
4040
/**
4141
* @param string $scopeName
4242
*
43+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
4344
* @return GetAllQueryIndexesOptions
4445
*/
4546
public function scopeName(string $scopeName): GetAllQueryIndexesOptions
@@ -51,6 +52,7 @@ public function scopeName(string $scopeName): GetAllQueryIndexesOptions
5152
/**
5253
* @param string $collectionName
5354
*
55+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
5456
* @return GetAllQueryIndexesOptions
5557
*/
5658
public function collectionName(string $collectionName): GetAllQueryIndexesOptions

Couchbase/Management/WatchQueryIndexesOptions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static function build(): WatchQueryIndexesOptions
4040
/**
4141
* @param string $scopeName
4242
*
43+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
4344
* @return WatchQueryIndexesOptions
4445
* @since 4.0.0
4546
*/
@@ -52,6 +53,7 @@ public function scopeName(string $scopeName): WatchQueryIndexesOptions
5253
/**
5354
* @param string $collectionName
5455
*
56+
* @deprecated 'Collection.queryIndexes()' should now be used for collection-related query index operations
5557
* @return WatchQueryIndexesOptions
5658
* @since 4.0.0
5759
*/

package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@
193193
<file role="php" name="BuildQueryIndexesOptions.php"/>
194194
<file role="php" name="ChangePasswordOptions.php"/>
195195
<file role="php" name="CollectionManager.php"/>
196+
<file role="php" name="CollectionQueryIndexManager.php"/>
196197
<file role="php" name="CollectionSpec.php"/>
197198
<file role="php" name="CompressionMode.php"/>
198199
<file role="php" name="ConflictResolutionType.php"/>

0 commit comments

Comments
 (0)