@@ -18,11 +18,15 @@ import (
18
18
"database/sql/driver"
19
19
"encoding/json"
20
20
"fmt"
21
+ "sync"
22
+ "time"
21
23
22
24
"github.com/pkg/errors"
23
25
24
26
"github.com/erda-project/erda/apistructs"
27
+ "github.com/erda-project/erda/modules/dop/services/apierrors"
25
28
"github.com/erda-project/erda/pkg/database/dbengine"
29
+ "github.com/erda-project/erda/pkg/strutil"
26
30
)
27
31
28
32
// TestCase 测试用例
@@ -188,3 +192,238 @@ func (client *DBClient) CleanTestCasesByTestSetID(projectID, testSetID uint64) e
188
192
func (client * DBClient ) BatchDeleteTestCases (ids []uint64 ) error {
189
193
return client .Where ("`id` IN (?)" , ids ).Delete (TestCase {}).Error
190
194
}
195
+
196
+ // order
197
+ const (
198
+ tcFieldPriority = "priority"
199
+ tcFieldID = "id"
200
+ tcFieldTestSetID = "test_set_id"
201
+ tcFieldTestSetIDV2 = "testSetID"
202
+ tcFieldUpdaterID = "updater_id"
203
+ tcFieldUpdaterIDV2 = "updaterID"
204
+ tcFieldUpdatedAt = "updated_at"
205
+ tcFieldUpdatedAtV2 = "updatedAt"
206
+ )
207
+
208
+ func (client * DBClient ) PagingTestCases (req apistructs.TestCasePagingRequest ) ([]TestCase , uint64 , error ) {
209
+ // validate request
210
+ if err := validateTestCasePagingRequest (req ); err != nil {
211
+ return nil , 0 , err
212
+ }
213
+ // set default for request
214
+ setDefaultForTestCasePagingRequest (& req )
215
+ // query base test set if necessary, then use `directory` to do `like` query
216
+ var baseTestSet TestSet
217
+ if req .TestSetID > 0 {
218
+ ts , err := client .GetTestSetByID (req .TestSetID )
219
+ if err != nil {
220
+ return nil , 0 , err
221
+ }
222
+ baseTestSet = * ts
223
+ }
224
+
225
+ baseSQL := client .DB .Table (TestCase {}.TableName () + " AS `tc`" ).Select ("*" )
226
+
227
+ // left join test_plan_case_relations
228
+ if len (req .NotInTestPlanIDs ) > 0 {
229
+ baseSQL = baseSQL .Joins (
230
+ "LEFT JOIN (" +
231
+ " SELECT * FROM " + TestPlanCaseRel {}.TableName ()+ " WHERE `test_plan_id` IN (?) GROUP BY `test_case_id`" +
232
+ ") AS `rel` ON `tc`.`id` = `rel`.`test_case_id`" ,
233
+ req .NotInTestPlanIDs ,
234
+ )
235
+ baseSQL = baseSQL .Where ("`rel`.`test_plan_id` IS NULL OR `rel`.`test_plan_id` NOT IN (?)" , req .NotInTestPlanIDs )
236
+ }
237
+
238
+ // left join test_sets
239
+ // use left join because test_set with id = 0 is not exists in test_sets table
240
+ baseSQL = baseSQL .Joins ("LEFT JOIN " + TestSet {}.TableName () + " AS `ts` ON `tc`.`test_set_id` = `ts`.`id`" )
241
+
242
+ // where clauses
243
+ // project id
244
+ baseSQL = baseSQL .Where ("`tc`.`project_id` = ?" , req .ProjectID )
245
+ // test set id
246
+ if req .TestSetID > 0 {
247
+ baseSQL = baseSQL .Where ("`ts`.`directory` LIKE '" + baseTestSet .Directory + "%'" )
248
+ }
249
+ // recycled
250
+ baseSQL = baseSQL .Where ("`tc`.`recycled` = ?" , req .Recycled )
251
+ // name
252
+ if req .Query != "" {
253
+ baseSQL = baseSQL .Where ("`tc`.`name` LIKE ?" , strutil .Concat ("%" , req .Query , "%" ))
254
+ }
255
+ // priority
256
+ if len (req .Priorities ) > 0 {
257
+ baseSQL = baseSQL .Where ("`tc`.`priority` IN (?)" , req .Priorities )
258
+ }
259
+ // updater
260
+ if len (req .UpdaterIDs ) > 0 {
261
+ baseSQL = baseSQL .Where ("`tc`.`updater_id` IN (?)" , req .UpdaterIDs )
262
+ }
263
+ // updatedAtBegin (Left closed Section)
264
+ if req .TimestampSecUpdatedAtBegin != nil {
265
+ t := time .Unix (int64 (* req .TimestampSecUpdatedAtBegin ), 0 )
266
+ req .UpdatedAtBeginInclude = & t
267
+ }
268
+ if req .UpdatedAtBeginInclude != nil {
269
+ baseSQL = baseSQL .Where ("`tc`.`updated_at` >= ?" , req .UpdatedAtBeginInclude )
270
+ }
271
+ // updatedAtEnd (Right closed Section)
272
+ if req .TimestampSecUpdatedAtEnd != nil {
273
+ t := time .Unix (int64 (* req .TimestampSecUpdatedAtEnd ), 0 )
274
+ req .UpdatedAtEndInclude = & t
275
+ }
276
+ if req .UpdatedAtEndInclude != nil {
277
+ baseSQL = baseSQL .Where ("`tc`.`updated_at` <= ?" , req .UpdatedAtEndInclude )
278
+ }
279
+ // testCaseIDs
280
+ if len (req .TestCaseIDs ) > 0 {
281
+ baseSQL = baseSQL .Where ("`tc`.`id` IN (?)" , req .TestCaseIDs )
282
+ }
283
+ if len (req .NotInTestCaseIDs ) > 0 {
284
+ baseSQL = baseSQL .Where ("`tc`.`id` NOT IN (?)" , req .NotInTestCaseIDs )
285
+ }
286
+
287
+ pagingSQL := baseSQL .NewScope (nil ).DB ()
288
+ countSQL := baseSQL .NewScope (nil ).DB ()
289
+
290
+ // order by fields
291
+ for _ , orderField := range req .OrderFields {
292
+ switch orderField {
293
+ case tcFieldID :
294
+ if req .OrderByIDAsc != nil {
295
+ pagingSQL = pagingSQL .Order ("`tc`.`id` ASC" )
296
+ }
297
+ if req .OrderByIDDesc != nil {
298
+ pagingSQL = pagingSQL .Order ("`tc`.`id` DESC" )
299
+ }
300
+ case tcFieldTestSetID , tcFieldTestSetIDV2 :
301
+ if req .OrderByTestSetIDAsc != nil {
302
+ pagingSQL = pagingSQL .Order ("`tc`.`test_set_id` ASC" )
303
+ }
304
+ if req .OrderByTestSetIDDesc != nil {
305
+ pagingSQL = pagingSQL .Order ("`tc`.`test_set_id` DESC" )
306
+ }
307
+ case tcFieldPriority :
308
+ if req .OrderByPriorityAsc != nil {
309
+ pagingSQL = pagingSQL .Order ("`tc`.`priority` ASC" )
310
+ }
311
+ if req .OrderByPriorityDesc != nil {
312
+ pagingSQL = pagingSQL .Order ("`tc`.`priority` DESC" )
313
+ }
314
+ case tcFieldUpdaterID , tcFieldUpdaterIDV2 :
315
+ if req .OrderByUpdaterIDAsc != nil {
316
+ pagingSQL = pagingSQL .Order ("`tc`.`updater_id` ASC" )
317
+ }
318
+ if req .OrderByUpdaterIDDesc != nil {
319
+ pagingSQL = pagingSQL .Order ("`tc`.`updater_id` DESC" )
320
+ }
321
+ case tcFieldUpdatedAt , tcFieldUpdatedAtV2 :
322
+ if req .OrderByUpdatedAtAsc != nil {
323
+ pagingSQL = pagingSQL .Order ("`tc`.`updated_at` ASC" )
324
+ }
325
+ if req .OrderByUpdatedAtDesc != nil {
326
+ pagingSQL = pagingSQL .Order ("`tc`.`updated_at` DESC" )
327
+ }
328
+ }
329
+ }
330
+
331
+ // concurrent do paging and count
332
+ var wg sync.WaitGroup
333
+ wg .Add (2 )
334
+
335
+ // result
336
+ var (
337
+ testCases []TestCase
338
+ total uint64
339
+ pagingErr , countErr error
340
+ )
341
+
342
+ // do paging
343
+ go func () {
344
+ defer wg .Done ()
345
+
346
+ // offset, limit
347
+ offset := (req .PageNo - 1 ) * req .PageSize
348
+ limit := req .PageSize
349
+ pagingErr = pagingSQL .Offset (offset ).Limit (limit ).Find (& testCases ).Error
350
+ }()
351
+
352
+ // do count
353
+ go func () {
354
+ defer wg .Done ()
355
+
356
+ // reset offset & limit before count
357
+ countErr = countSQL .Offset (0 ).Limit (- 1 ).Count (& total ).Error
358
+ }()
359
+
360
+ // wait
361
+ wg .Wait ()
362
+
363
+ if pagingErr != nil {
364
+ return nil , 0 , apierrors .ErrPagingTestCases .InternalError (pagingErr )
365
+ }
366
+ if countErr != nil {
367
+ return nil , 0 , apierrors .ErrPagingTestCases .InternalError (countErr )
368
+ }
369
+
370
+ return testCases , total , nil
371
+ }
372
+
373
+ func validateTestCasePagingRequest (req apistructs.TestCasePagingRequest ) error {
374
+ if req .ProjectID == 0 {
375
+ return apierrors .ErrPagingTestCases .MissingParameter ("projectID" )
376
+ }
377
+ for _ , priority := range req .Priorities {
378
+ if ! priority .IsValid () {
379
+ return apierrors .ErrPagingTestCases .InvalidParameter (fmt .Sprintf ("priority: %s" , priority ))
380
+ }
381
+ }
382
+ if req .OrderByPriorityAsc != nil && req .OrderByPriorityDesc != nil {
383
+ return apierrors .ErrPagingTestCases .InvalidParameter ("order by priority ASC or DESC?" )
384
+ }
385
+ if req .OrderByUpdaterIDAsc != nil && req .OrderByUpdaterIDDesc != nil {
386
+ return apierrors .ErrPagingTestCases .InvalidParameter ("order by updaterID ASC or DESC?" )
387
+ }
388
+ if req .OrderByUpdatedAtAsc != nil && req .OrderByUpdatedAtDesc != nil {
389
+ return apierrors .ErrPagingTestCases .InvalidParameter ("order by updatedAt ASC or DESC?" )
390
+ }
391
+ if req .OrderByIDAsc != nil && req .OrderByIDDesc != nil {
392
+ return apierrors .ErrPagingTestCases .InvalidParameter ("order by id ASC or DESC?" )
393
+ }
394
+ if req .OrderByTestSetIDAsc != nil && req .OrderByTestSetIDDesc != nil {
395
+ return apierrors .ErrPagingTestCases .InvalidParameter ("order by testSetID ASC or DESC?" )
396
+ }
397
+ if req .OrderByTestSetNameAsc != nil && req .OrderByTestSetNameDesc != nil {
398
+ return apierrors .ErrPagingTestCases .InvalidParameter ("order by testSetName ASC or DESC?" )
399
+ }
400
+
401
+ return nil
402
+ }
403
+
404
+ func setDefaultForTestCasePagingRequest (req * apistructs.TestCasePagingRequest ) {
405
+ // must order by testSet
406
+ if req .OrderByTestSetIDAsc == nil && req .OrderByTestSetIDDesc == nil &&
407
+ req .OrderByTestSetNameAsc == nil && req .OrderByTestSetNameDesc == nil {
408
+ // default order by `test_set_id` ASC
409
+ req .OrderByTestSetIDAsc = & []bool {true }[0 ]
410
+ req .OrderFields = append (req .OrderFields , tcFieldTestSetID )
411
+ }
412
+
413
+ // set default order inside a testSet
414
+ if req .OrderByPriorityAsc == nil && req .OrderByPriorityDesc == nil &&
415
+ req .OrderByUpdaterIDAsc == nil && req .OrderByUpdaterIDDesc == nil &&
416
+ req .OrderByUpdatedAtAsc == nil && req .OrderByUpdatedAtDesc == nil &&
417
+ req .OrderByIDAsc == nil && req .OrderByIDDesc == nil {
418
+ // default order by `id` ASC
419
+ req .OrderByIDAsc = & []bool {true }[0 ]
420
+ req .OrderFields = append (req .OrderFields , tcFieldID )
421
+ }
422
+
423
+ if req .PageNo == 0 {
424
+ req .PageNo = 1
425
+ }
426
+ if req .PageSize == 0 {
427
+ req .PageSize = 20
428
+ }
429
+ }
0 commit comments