@@ -5136,6 +5136,187 @@ func TestVTExplain(t *testing.T) {
5136
5136
}
5137
5137
}
5138
5138
5139
+ func TestVExplain (t * testing.T ) {
5140
+ tests := []struct {
5141
+ name string
5142
+ keyspaces []* vtctldatapb.Keyspace
5143
+ shards []* vtctldatapb.Shard
5144
+ srvVSchema * vschemapb.SrvVSchema
5145
+ tabletSchemas map [string ]* tabletmanagerdatapb.SchemaDefinition
5146
+ tablets []* vtadminpb.Tablet
5147
+ req * vtadminpb.VExplainRequest
5148
+ expectedError error
5149
+ }{
5150
+ {
5151
+ name : "returns an error if cluster unspecified in request" ,
5152
+ req : & vtadminpb.VExplainRequest {
5153
+ Keyspace : "commerce" ,
5154
+ Sql : "vexplain all select * from customers" ,
5155
+ },
5156
+ expectedError : vtadminerrors .ErrInvalidRequest ,
5157
+ },
5158
+ {
5159
+ name : "returns an error if keyspace unspecified in request" ,
5160
+ req : & vtadminpb.VExplainRequest {
5161
+ ClusterId : "c0" ,
5162
+ Sql : "vexplain all select * from customers" ,
5163
+ },
5164
+ expectedError : vtadminerrors .ErrInvalidRequest ,
5165
+ },
5166
+ {
5167
+ name : "returns an error if SQL unspecified in request" ,
5168
+ req : & vtadminpb.VExplainRequest {
5169
+ ClusterId : "c0" ,
5170
+ Keyspace : "commerce" ,
5171
+ },
5172
+ expectedError : vtadminerrors .ErrInvalidRequest ,
5173
+ },
5174
+ {
5175
+ name : "runs VExplain given a valid request in a valid topology" ,
5176
+ keyspaces : []* vtctldatapb.Keyspace {
5177
+ {
5178
+ Name : "commerce" ,
5179
+ Keyspace : & topodatapb.Keyspace {},
5180
+ },
5181
+ },
5182
+ shards : []* vtctldatapb.Shard {
5183
+ {
5184
+ Name : "-" ,
5185
+ Keyspace : "commerce" ,
5186
+ },
5187
+ },
5188
+ srvVSchema : & vschemapb.SrvVSchema {
5189
+ Keyspaces : map [string ]* vschemapb.Keyspace {
5190
+ "commerce" : {
5191
+ Sharded : false ,
5192
+ Tables : map [string ]* vschemapb.Table {
5193
+ "customers" : {},
5194
+ },
5195
+ },
5196
+ },
5197
+ RoutingRules : & vschemapb.RoutingRules {
5198
+ Rules : []* vschemapb.RoutingRule {},
5199
+ },
5200
+ },
5201
+ tabletSchemas : map [string ]* tabletmanagerdatapb.SchemaDefinition {
5202
+ "c0_cell1-0000000100" : {
5203
+ DatabaseSchema : "CREATE DATABASE commerce" ,
5204
+ TableDefinitions : []* tabletmanagerdatapb.TableDefinition {
5205
+ {
5206
+ Name : "t1" ,
5207
+ Schema : `CREATE TABLE customers (id int(11) not null,PRIMARY KEY (id));` ,
5208
+ Type : "BASE" ,
5209
+ Columns : []string {"id" },
5210
+ DataLength : 100 ,
5211
+ RowCount : 50 ,
5212
+ Fields : []* querypb.Field {
5213
+ {
5214
+ Name : "id" ,
5215
+ Type : querypb .Type_INT32 ,
5216
+ },
5217
+ },
5218
+ },
5219
+ },
5220
+ },
5221
+ },
5222
+ tablets : []* vtadminpb.Tablet {
5223
+ {
5224
+ Cluster : & vtadminpb.Cluster {
5225
+ Id : "c0" ,
5226
+ Name : "cluster0" ,
5227
+ },
5228
+ State : vtadminpb .Tablet_SERVING ,
5229
+ Tablet : & topodatapb.Tablet {
5230
+ Alias : & topodatapb.TabletAlias {
5231
+ Uid : 100 ,
5232
+ Cell : "c0_cell1" ,
5233
+ },
5234
+ Hostname : "tablet-cell1-a" ,
5235
+ Keyspace : "commerce" ,
5236
+ Shard : "-" ,
5237
+ Type : topodatapb .TabletType_REPLICA ,
5238
+ },
5239
+ },
5240
+ },
5241
+ req : & vtadminpb.VExplainRequest {
5242
+ ClusterId : "c0" ,
5243
+ Keyspace : "commerce" ,
5244
+ Sql : "vexplain all select * from customers" ,
5245
+ },
5246
+ },
5247
+ }
5248
+
5249
+ for _ , tt := range tests {
5250
+ t .Run (tt .name , func (t * testing.T ) {
5251
+ ctx , cancel := context .WithCancel (context .Background ())
5252
+ defer cancel ()
5253
+ toposerver := memorytopo .NewServer (ctx , "c0_cell1" )
5254
+
5255
+ tmc := testutil.TabletManagerClient {
5256
+ GetSchemaResults : map [string ]struct {
5257
+ Schema * tabletmanagerdatapb.SchemaDefinition
5258
+ Error error
5259
+ }{},
5260
+ }
5261
+
5262
+ vtctldserver := testutil .NewVtctldServerWithTabletManagerClient (t , toposerver , & tmc , func (ts * topo.Server ) vtctlservicepb.VtctldServer {
5263
+ return grpcvtctldserver .NewVtctldServer (vtenv .NewTestEnv (), ts )
5264
+ })
5265
+
5266
+ testutil .WithTestServer (ctx , t , vtctldserver , func (t * testing.T , vtctldClient vtctldclient.VtctldClient ) {
5267
+ if tt .srvVSchema != nil {
5268
+ err := toposerver .UpdateSrvVSchema (ctx , "c0_cell1" , tt .srvVSchema )
5269
+ require .NoError (t , err )
5270
+ }
5271
+ testutil .AddKeyspaces (ctx , t , toposerver , tt .keyspaces ... )
5272
+ testutil .AddShards (ctx , t , toposerver , tt .shards ... )
5273
+
5274
+ for _ , tablet := range tt .tablets {
5275
+ testutil .AddTablet (ctx , t , toposerver , tablet .Tablet , nil )
5276
+
5277
+ // Adds each SchemaDefinition to the fake TabletManagerClient, or nil
5278
+ // if there are no schemas for that tablet. (All tablet aliases must
5279
+ // exist in the map. Otherwise, TabletManagerClient will return an error when
5280
+ // looking up the schema with tablet alias that doesn't exist.)
5281
+ alias := topoproto .TabletAliasString (tablet .Tablet .Alias )
5282
+ tmc .GetSchemaResults [alias ] = struct {
5283
+ Schema * tabletmanagerdatapb.SchemaDefinition
5284
+ Error error
5285
+ }{
5286
+ Schema : tt .tabletSchemas [alias ],
5287
+ Error : nil ,
5288
+ }
5289
+ }
5290
+
5291
+ clusters := []* cluster.Cluster {
5292
+ vtadmintestutil .BuildCluster (t , vtadmintestutil.TestClusterConfig {
5293
+ Cluster : & vtadminpb.Cluster {
5294
+ Id : "c0" ,
5295
+ Name : "cluster0" ,
5296
+ },
5297
+ VtctldClient : vtctldClient ,
5298
+ Tablets : tt .tablets ,
5299
+ }),
5300
+ }
5301
+
5302
+ api := NewAPI (vtenv .NewTestEnv (), clusters , Options {})
5303
+ resp , err := api .VExplain (ctx , tt .req )
5304
+
5305
+ if tt .expectedError != nil {
5306
+ assert .True (t , errors .Is (err , tt .expectedError ), "expected error type %w does not match actual error type %w" , err , tt .expectedError )
5307
+ } else {
5308
+ require .NoError (t , err )
5309
+
5310
+ // We don't particularly care to test the contents of the VExplain response,
5311
+ // just that it exists.
5312
+ print (resp .Response )
5313
+ assert .NotEmpty (t , resp .Response )
5314
+ }
5315
+ })
5316
+ })
5317
+ }
5318
+ }
5319
+
5139
5320
type ServeHTTPVtctldResponse struct {
5140
5321
Result ServeHTTPVtctldResult `json:"result"`
5141
5322
Ok bool `json:"ok"`
0 commit comments