Skip to content

Commit f1dbfbf

Browse files
committedSep 16, 2024
group by generic way
1 parent 6f7dc6d commit f1dbfbf

File tree

6 files changed

+429
-285
lines changed

6 files changed

+429
-285
lines changed
 

‎pkg/clientinteractor/interactor.go

+57-9
Original file line numberDiff line numberDiff line change
@@ -1285,24 +1285,46 @@ func (pi *PSQLInteractor) KillClient(clientID uint) error {
12851285
//
12861286
// Returns:
12871287
// - error: An error if any occurred during the operation.
1288-
func (pi *PSQLInteractor) BackendConnections(ctx context.Context, shs []shard.Shardinfo) error {
1289-
if err := pi.WriteHeader("backend connection id", "router", "shard key name", "hostname", "pid", "user", "dbname", "sync", "tx_served", "tx status"); err != nil {
1288+
func (pi *PSQLInteractor) BackendConnections(ctx context.Context, shs []shard.Shardinfo, groupByClause *spqrparser.Group) error {
1289+
headers := []string{"backend connection id", "router", "shard key name", "hostname", "pid", "user", "dbname", "sync", "tx_served", "tx status"}
1290+
getters := []func(sh shard.Shardinfo) string{
1291+
func(sh shard.Shardinfo) string { return fmt.Sprintf("%d", sh.ID()) },
1292+
func(sh shard.Shardinfo) string {
1293+
router := "no data"
1294+
s, ok := sh.(shard.CoordShardinfo)
1295+
if ok {
1296+
router = s.Router()
1297+
}
1298+
return router
1299+
},
1300+
func(sh shard.Shardinfo) string { return sh.ShardKeyName() },
1301+
func(sh shard.Shardinfo) string { return sh.InstanceHostname() },
1302+
func(sh shard.Shardinfo) string { return fmt.Sprintf("%d", sh.Pid()) },
1303+
func(sh shard.Shardinfo) string { return sh.Usr() },
1304+
func(sh shard.Shardinfo) string { return sh.DB() },
1305+
func(sh shard.Shardinfo) string { return strconv.FormatInt(sh.Sync(), 10) },
1306+
func(sh shard.Shardinfo) string { return strconv.FormatInt(sh.TxServed(), 10) },
1307+
func(sh shard.Shardinfo) string { return sh.TxStatus().String() },
1308+
}
1309+
1310+
if groupByClause != nil {
1311+
return groupBy(headers, shs, getters, groupByClause.Col.ColName, pi)
1312+
}
1313+
1314+
if err := pi.WriteHeader(headers...); err != nil {
12901315
spqrlog.Zero.Error().Err(err).Msg("")
12911316
return err
12921317
}
12931318

12941319
for _, sh := range shs {
1295-
router := "no data"
1296-
s, ok := sh.(shard.CoordShardinfo)
1297-
if ok {
1298-
router = s.Router()
1320+
vals := []string{}
1321+
for _, getter := range getters {
1322+
vals = append(vals, getter(sh))
12991323
}
1300-
1301-
if err := pi.WriteDataRow(fmt.Sprintf("%d", sh.ID()), router, sh.ShardKeyName(), sh.InstanceHostname(), fmt.Sprintf("%d", sh.Pid()), sh.Usr(), sh.DB(), strconv.FormatInt(sh.Sync(), 10), strconv.FormatInt(sh.TxServed(), 10), sh.TxStatus().String()); err != nil {
1324+
if err := pi.WriteDataRow(vals...); err != nil {
13021325
spqrlog.Zero.Error().Err(err).Msg("")
13031326
return err
13041327
}
1305-
13061328
}
13071329

13081330
return pi.CompleteMsg(len(shs))
@@ -1390,3 +1412,29 @@ func (pi *PSQLInteractor) PreparedStatements(ctx context.Context, shs []shard.Pr
13901412

13911413
return pi.CompleteMsg(len(shs))
13921414
}
1415+
1416+
func groupBy[T any](headers []string, values []T, getters []func(s T) string, groupBy string, pi *PSQLInteractor) error {
1417+
ind := -1
1418+
for i, header := range headers {
1419+
if header == groupBy {
1420+
if err := pi.WriteHeader(groupBy, "count"); err != nil {
1421+
return err
1422+
}
1423+
ind = i
1424+
break
1425+
}
1426+
}
1427+
1428+
cnt := make(map[string]int)
1429+
for _, value := range values {
1430+
cnt[getters[ind](value)]++
1431+
}
1432+
1433+
for k, v := range cnt {
1434+
if err := pi.WriteDataRow(k, fmt.Sprintf("%d", v)); err != nil {
1435+
return err
1436+
}
1437+
}
1438+
1439+
return pi.CompleteMsg(len(cnt))
1440+
}

‎pkg/meta/meta.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,11 @@ func ProcessShow(ctx context.Context, stmt *spqrparser.Show, mngr EntityMgr, ci
452452
return err
453453
}
454454

455-
return cli.BackendConnections(ctx, resp)
455+
var groupBy *spqrparser.Group
456+
if stmt.Group != nil {
457+
groupBy = stmt.Group.(*spqrparser.Group)
458+
}
459+
return cli.BackendConnections(ctx, resp, groupBy)
456460
case spqrparser.ShardsStr:
457461
shards, err := mngr.ListShards(ctx)
458462
if err != nil {

‎test/feature/features/coordinator_show.feature

+55
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,61 @@ Feature: Coordinator show clients, pools and backend_connections
313313
]
314314
"""
315315

316+
Scenario: show backend_connections group by
317+
When I run SQL on host "coordinator"
318+
"""
319+
SHOW backend_connections group by hostname
320+
"""
321+
Then command return code should be "0"
322+
And SQL result should match json
323+
"""
324+
[
325+
{
326+
"hostname":"spqr_shard_1:6432",
327+
"count": "2"
328+
}
329+
]
330+
"""
331+
And SQL result should match json
332+
"""
333+
[
334+
{
335+
"hostname":"spqr_shard_2:6432",
336+
"count": "2"
337+
}
338+
]
339+
"""
340+
341+
When I run SQL on host "coordinator"
342+
"""
343+
SHOW backend_connections group by user
344+
"""
345+
Then command return code should be "0"
346+
And SQL result should match json
347+
"""
348+
[
349+
{
350+
"user":"regress",
351+
"count": "4"
352+
}
353+
]
354+
"""
355+
356+
When I run SQL on host "coordinator"
357+
"""
358+
SHOW backend_connections group by dbname
359+
"""
360+
Then command return code should be "0"
361+
And SQL result should match json
362+
"""
363+
[
364+
{
365+
"dbname":"regress",
366+
"count": "4"
367+
}
368+
]
369+
"""
370+
316371
Scenario: show pools works
317372
When I run SQL on host "coordinator"
318373
"""

‎yacc/console/ast.go

+8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ type Order struct {
2323
Col ColumnRef
2424
}
2525

26+
type GroupClause interface{}
27+
28+
type Group struct {
29+
GroupClause
30+
Col ColumnRef
31+
}
32+
2633
type WhereClauseNode interface {
2734
}
2835

@@ -50,6 +57,7 @@ type Show struct {
5057
Cmd string
5158
Where WhereClauseNode
5259
Order OrderClause
60+
Group GroupClause
5361
}
5462

5563
type Set struct {

0 commit comments

Comments
 (0)