Skip to content

Commit 727da99

Browse files
committed
feat: expand parity matrix and capability ergonomics
1 parent 891e2d9 commit 727da99

10 files changed

Lines changed: 210 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
* Added fluent boolean grouping APIs (`orWhere`, `whereOpen/whereClose`, `orHaving`, `havingOpen/havingClose`) and JOIN builders (`join`, `innerJoin`, `leftJoin`, `rightJoin`, `crossJoin`)
1010
* Added `orderByKnn()` and broader helper wrappers for operational and Manticore-oriented commands (`SHOW PROFILE/PLAN/THREADS/VERSION/PLUGINS`, table status/settings/indexes, flush/reload/kill, suggest family)
1111
* Added capability discovery and feature-gating APIs (`Capabilities`, `getCapabilities()`, `supports()`, `requireSupport()`) with `UnsupportedFeatureException` for unsupported command families
12+
* Added `SphinxQL::requireSupport()` passthrough and convenience engine predicates on `Capabilities` (`isManticore`, `isSphinx2`, `isSphinx3`)
13+
* Added helper parity wrappers for `SHOW CHARACTER SET` and `SHOW COLLATION`
14+
* Added `docs/feature-matrix.yml` as a feature-level support map across Sphinx2/Sphinx3/Manticore
1215
* Added capability-aware runtime tests for optional engine features (`supportsCommand`, Buddy-gated checks)
1316
* Added and stabilized Sphinx 3 compatibility coverage while preserving Sphinx 2 and Manticore test behavior
1417
* Migrated CI to GitHub Actions-only validation with strict composer metadata checks

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ We support the following database connection drivers:
9090
| Sphinx 3.x | Supported | Supported with engine-specific assertions | Full CI lane |
9191
| Manticore | Supported | Supported + Percolate | Full CI lane |
9292

93+
Detailed feature-level support is tracked in [`docs/feature-matrix.yml`](docs/feature-matrix.yml).
94+
9395
### Migration to 4.0
9496

9597
See [`MIGRATING-4.0.md`](MIGRATING-4.0.md) for the complete migration checklist,
@@ -452,6 +454,12 @@ Remember to `->execute()` to get a result.
452454

453455
Throws `UnsupportedFeatureException` when the requested feature is not available.
454456

457+
`SphinxQL` also exposes capability helpers:
458+
459+
* __$sphinxql->getCapabilities()__
460+
* __$sphinxql->supports($feature)__
461+
* __$sphinxql->requireSupport($feature, $context = '')__
462+
455463
The following methods return a prepared `SphinxQL` object. You can also use `->enqueue($next_object)`:
456464

457465
```php
@@ -481,6 +489,8 @@ $result = (new SphinxQL($this->conn))
481489
* `(new Helper($conn))->showAgentStatus() => 'SHOW AGENT STATUS'`
482490
* `(new Helper($conn))->showScroll() => 'SHOW SCROLL'`
483491
* `(new Helper($conn))->showDatabases() => 'SHOW DATABASES'`
492+
* `(new Helper($conn))->showCharacterSet() => 'SHOW CHARACTER SET'`
493+
* `(new Helper($conn))->showCollation() => 'SHOW COLLATION'`
484494
* `(new Helper($conn))->showTables() => 'SHOW TABLES'`
485495
* `(new Helper($conn))->showVariables() => 'SHOW VARIABLES'`
486496
* `(new Helper($conn))->showCreateTable($table)`

docs/feature-matrix.yml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
version: 1
2+
updated_at: "2026-02-27"
3+
notes:
4+
- "supported means covered by runtime tests in at least one CI lane."
5+
- "conditional means feature depends on engine/runtime capability checks."
6+
7+
builder:
8+
grouped_where:
9+
api: ["where", "orWhere", "whereOpen", "orWhereOpen", "whereClose"]
10+
sphinx2: supported
11+
sphinx3: supported
12+
manticore: supported
13+
grouped_having:
14+
api: ["having", "orHaving", "havingOpen", "orHavingOpen", "havingClose"]
15+
sphinx2: supported
16+
sphinx3: supported
17+
manticore: supported
18+
joins:
19+
api: ["join", "innerJoin", "leftJoin", "rightJoin", "crossJoin", "resetJoins"]
20+
sphinx2: supported
21+
sphinx3: supported
22+
manticore: supported
23+
order_by_knn_builder:
24+
api: ["orderByKnn"]
25+
sphinx2: supported
26+
sphinx3: supported
27+
manticore: supported
28+
notes:
29+
- "builder-level SQL generation is supported; backend execution support depends on engine/runtime."
30+
31+
helper:
32+
core_show:
33+
api:
34+
- "showMeta"
35+
- "showWarnings"
36+
- "showStatus"
37+
- "showTables"
38+
- "showVariables"
39+
- "showDatabases"
40+
- "showCharacterSet"
41+
- "showCollation"
42+
sphinx2: supported
43+
sphinx3: supported
44+
manticore: supported
45+
diagnostic_show:
46+
api: ["showProfile", "showPlan", "showThreads", "showPlugins", "showQueries"]
47+
sphinx2: conditional
48+
sphinx3: conditional
49+
manticore: conditional
50+
table_introspection:
51+
api: ["showCreateTable", "showTableStatus", "showTableSettings", "showTableIndexes"]
52+
sphinx2: conditional
53+
sphinx3: conditional
54+
manticore: conditional
55+
maintenance:
56+
api:
57+
- "flushRtIndex"
58+
- "truncateRtIndex"
59+
- "optimizeIndex"
60+
- "showIndexStatus"
61+
- "flushRamchunk"
62+
- "flushAttributes"
63+
- "flushHostnames"
64+
- "flushLogs"
65+
- "reloadPlugins"
66+
- "kill"
67+
sphinx2: conditional
68+
sphinx3: conditional
69+
manticore: conditional
70+
suggest_family:
71+
api: ["callSuggest", "callQSuggest", "callAutocomplete"]
72+
sphinx2: conditional
73+
sphinx3: conditional
74+
manticore: conditional
75+
notes:
76+
- "callQSuggest/callAutocomplete are feature-gated and throw UnsupportedFeatureException when unavailable."
77+
78+
capabilities:
79+
api: ["Helper.getCapabilities", "Helper.supports", "Helper.requireSupport", "SphinxQL.getCapabilities", "SphinxQL.supports"]
80+
sphinx2: supported
81+
sphinx3: supported
82+
manticore: supported

docs/helper.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Available Methods
3030
- ``showAgentStatus()``
3131
- ``showScroll()``
3232
- ``showDatabases()``
33+
- ``showCharacterSet()``
34+
- ``showCollation()``
3335
- ``showTables($index)``
3436
- ``showVariables()``
3537
- ``showCreateTable($table)``

docs/query-builder.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,4 @@ Capability Introspection
9191

9292
- ``getCapabilities()``
9393
- ``supports($feature)``
94+
- ``requireSupport($feature, $context = '')``

src/Capabilities.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,30 @@ public function getFeatures()
5858
return $this->features;
5959
}
6060

61+
/**
62+
* @return bool
63+
*/
64+
public function isManticore()
65+
{
66+
return $this->engine === 'MANTICORE';
67+
}
68+
69+
/**
70+
* @return bool
71+
*/
72+
public function isSphinx2()
73+
{
74+
return $this->engine === 'SPHINX2';
75+
}
76+
77+
/**
78+
* @return bool
79+
*/
80+
public function isSphinx3()
81+
{
82+
return $this->engine === 'SPHINX3';
83+
}
84+
6185
/**
6286
* @param string $feature
6387
*
@@ -80,4 +104,3 @@ public function toArray()
80104
);
81105
}
82106
}
83-

src/Helper.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,26 @@ public function showDatabases()
186186
return $this->query('SHOW DATABASES');
187187
}
188188

189+
/**
190+
* Runs query: SHOW CHARACTER SET
191+
*
192+
* @return SphinxQL
193+
*/
194+
public function showCharacterSet()
195+
{
196+
return $this->query('SHOW CHARACTER SET');
197+
}
198+
199+
/**
200+
* Runs query: SHOW COLLATION
201+
*
202+
* @return SphinxQL
203+
*/
204+
public function showCollation()
205+
{
206+
return $this->query('SHOW COLLATION');
207+
}
208+
189209
/**
190210
* Runs query: SHOW TABLES
191211
*
@@ -275,6 +295,8 @@ public function supports($feature)
275295
'show_threads',
276296
'show_plugins',
277297
'show_queries',
298+
'show_character_set',
299+
'show_collation',
278300
'show_table_settings',
279301
'show_table_indexes',
280302
'call_suggest',
@@ -297,6 +319,8 @@ public function supports($feature)
297319
'show_threads' => 'SHOW THREADS',
298320
'show_plugins' => 'SHOW PLUGINS',
299321
'show_queries' => 'SHOW QUERIES',
322+
'show_character_set' => 'SHOW CHARACTER SET',
323+
'show_collation' => 'SHOW COLLATION',
300324
'show_table_settings' => 'SHOW TABLE rt SETTINGS',
301325
'show_table_indexes' => 'SHOW TABLE rt INDEXES',
302326
'call_suggest' => "CALL SUGGEST('teh', 'rt')",

src/SphinxQL.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,26 @@ public function supports($feature)
294294
return (new Helper($this->connection))->supports($feature);
295295
}
296296

297+
/**
298+
* Throws when a named feature is not supported.
299+
*
300+
* @param string $feature
301+
* @param string $context
302+
*
303+
* @return self
304+
* @throws SphinxQLException
305+
*/
306+
public function requireSupport($feature, $context = '')
307+
{
308+
if ($this->connection === null) {
309+
throw new SphinxQLException('requireSupport() requires an attached connection.');
310+
}
311+
312+
(new Helper($this->connection))->requireSupport($feature, $context);
313+
314+
return $this;
315+
}
316+
297317
/**
298318
* Avoids having the expressions escaped
299319
*

tests/SphinxQL/HelperTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@ public function testMiscellaneous()
283283
$query = $this->createHelper()->showDatabases();
284284
$this->assertEquals('SHOW DATABASES', $query->compile()->getCompiled());
285285

286+
$query = $this->createHelper()->showCharacterSet();
287+
$this->assertEquals('SHOW CHARACTER SET', $query->compile()->getCompiled());
288+
289+
$query = $this->createHelper()->showCollation();
290+
$this->assertEquals('SHOW COLLATION', $query->compile()->getCompiled());
291+
286292
$query = $this->createHelper()->showCreateTable('rt');
287293
$this->assertEquals('SHOW CREATE TABLE rt', $query->compile()->getCompiled());
288294

@@ -432,6 +438,11 @@ public function testCapabilitiesAndSupports()
432438
$this->assertNotEmpty($caps->getEngine());
433439
$this->assertTrue($this->createHelper()->supports('grouped_where'));
434440
$this->assertIsBool($this->createHelper()->supports('show_profile'));
441+
$this->assertIsBool($this->createHelper()->supports('show_character_set'));
442+
$this->assertIsBool($this->createHelper()->supports('show_collation'));
443+
$this->assertSame($caps->isManticore(), $caps->getEngine() === 'MANTICORE');
444+
$this->assertSame($caps->isSphinx2(), $caps->getEngine() === 'SPHINX2');
445+
$this->assertSame($caps->isSphinx3(), $caps->getEngine() === 'SPHINX3');
435446
}
436447

437448
public function testSupportsUnknownFeatureValidation()
@@ -473,6 +484,26 @@ public function testShowPluginsExecutionWhenSupported()
473484
$this->assertIsArray($rows);
474485
}
475486

487+
public function testShowCharacterSetExecutionWhenSupported()
488+
{
489+
if (!TestUtil::supportsCommand($this->conn, 'SHOW CHARACTER SET')) {
490+
$this->markTestSkipped('SHOW CHARACTER SET is not supported by this engine.');
491+
}
492+
493+
$rows = $this->createHelper()->showCharacterSet()->execute()->getStored();
494+
$this->assertIsArray($rows);
495+
}
496+
497+
public function testShowCollationExecutionWhenSupported()
498+
{
499+
if (!TestUtil::supportsCommand($this->conn, 'SHOW COLLATION')) {
500+
$this->markTestSkipped('SHOW COLLATION is not supported by this engine.');
501+
}
502+
503+
$rows = $this->createHelper()->showCollation()->execute()->getStored();
504+
$this->assertIsArray($rows);
505+
}
506+
476507
public function testSuggestExecutionWhenSupported()
477508
{
478509
if (!TestUtil::supportsCommand($this->conn, "CALL SUGGEST('teh', 'rt')")) {

tests/SphinxQL/SphinxQLTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,19 @@ public function testSphinxQLCapabilitiesAccess()
13911391
$this->assertTrue($query->supports('grouped_where'));
13921392
}
13931393

1394+
public function testSphinxQLRequireSupport()
1395+
{
1396+
$query = $this->createSphinxQL();
1397+
if ($query->supports('call_qsuggest')) {
1398+
$this->assertSame($query, $query->requireSupport('call_qsuggest'));
1399+
1400+
return;
1401+
}
1402+
1403+
$this->expectException(Foolz\SphinxQL\Exception\UnsupportedFeatureException::class);
1404+
$query->requireSupport('call_qsuggest');
1405+
}
1406+
13941407
public function testSphinxQLSupportsUnknownFeatureValidation()
13951408
{
13961409
$this->expectException(Foolz\SphinxQL\Exception\SphinxQLException::class);

0 commit comments

Comments
 (0)