@@ -409,3 +409,144 @@ func TestIssue1456TooManyUnknownTransactions(t *testing.T) {
409409 wg .Wait ()
410410 })
411411}
412+
413+ func TestQueryResultSet (t * testing.T ) {
414+ if version .Lt (os .Getenv ("YDB_VERSION" ), "24.1" ) {
415+ t .Skip ("query service not allowed in YDB version '" + os .Getenv ("YDB_VERSION" ) + "'" )
416+ }
417+
418+ t .Run ("OK" , func (t * testing.T ) {
419+ scope := newScope (t )
420+
421+ partSizeBytes := 1000
422+ targetCount := partSizeBytes * 10 // for guarantee size of response will contain many parts
423+ items := make ([]types.Value , 0 , targetCount )
424+ for i := 0 ; i < targetCount ; i ++ {
425+ item := types .StructValue (
426+ types .StructFieldValue ("val" , types .Int64Value (int64 (i ))),
427+ )
428+ items = append (items , item )
429+ }
430+
431+ err := scope .Driver ().Query ().DoTx (scope .Ctx , func (ctx context.Context , tx query.TxActor ) error {
432+ rs , err := tx .QueryResultSet (ctx , `
433+ DECLARE $arg AS List<Struct<val: Int64>>;
434+
435+ SELECT * FROM AS_TABLE($arg);
436+ ` ,
437+ query .WithParameters (ydb .ParamsBuilder ().Param ("$arg" ).Any (types .ListValue (items ... )).Build ()),
438+ query .WithResponsePartLimitSizeBytes (int64 (partSizeBytes )),
439+ )
440+ if err != nil {
441+ return err
442+ }
443+
444+ for i := 0 ; i < targetCount ; i ++ {
445+ row , err := rs .NextRow (ctx )
446+ if err != nil {
447+ return err
448+ }
449+
450+ var val int64
451+ err = row .Scan (& val )
452+ require .NoError (t , err )
453+ require .Equal (t , int64 (i ), val )
454+ }
455+
456+ return nil
457+ })
458+ require .NoError (t , err )
459+ })
460+ t .Run ("FailOnSecondResultSet" , func (t * testing.T ) {
461+ scope := newScope (t )
462+
463+ var secondRowError error
464+ err := scope .Driver ().Query ().DoTx (scope .Ctx , func (ctx context.Context , tx query.TxActor ) error {
465+ rs , err := tx .QueryResultSet (ctx , "SELECT 1; SELECT 2" )
466+ if err != nil {
467+ return err
468+ }
469+
470+ _ , err = rs .NextRow (ctx )
471+ if err != nil {
472+ return err
473+ }
474+
475+ _ , secondRowError = rs .NextRow (ctx )
476+
477+ return nil
478+ })
479+ require .NoError (t , err )
480+ require .Error (t , secondRowError )
481+ require .NotErrorIs (t , secondRowError , io .EOF )
482+ })
483+ }
484+
485+ func TestQueryPartLimiter (t * testing.T ) {
486+ if os .Getenv ("YDB_VERSION" ) != "nightly" && version .Lt (os .Getenv ("YDB_VERSION" ), "25.0" ) {
487+ t .Skip ("require enables transactions for topics" )
488+ }
489+
490+ scope := newScope (t )
491+
492+ var readPartCount int
493+ scope .Driver (ydb .WithTraceQuery (trace.Query {
494+ OnResultNextPart : func (info trace.QueryResultNextPartStartInfo ) func (info trace.QueryResultNextPartDoneInfo ) {
495+ return func (info trace.QueryResultNextPartDoneInfo ) {
496+ if info .Error == nil {
497+ readPartCount ++
498+ }
499+ }
500+ },
501+ }))
502+
503+ targetCount := 1000
504+ items := make ([]types.Value , 0 , targetCount )
505+ for i := 0 ; i < targetCount ; i ++ {
506+ item := types .StructValue (
507+ types .StructFieldValue ("val" , types .Int64Value (int64 (i ))),
508+ )
509+ items = append (items , item )
510+ }
511+
512+ getPartCount := func (partSize int64 ) int {
513+ partCount := 0
514+ err := scope .Driver ().Query ().DoTx (scope .Ctx , func (ctx context.Context , tx query.TxActor ) error {
515+ oldParts := readPartCount
516+ rs , err := tx .QueryResultSet (ctx , `
517+ DECLARE $arg AS List<Struct<val: Int64>>;
518+
519+ SELECT * FROM AS_TABLE($arg);
520+ ` ,
521+ query .WithParameters (ydb .ParamsBuilder ().Param ("$arg" ).Any (types .ListValue (items ... )).Build ()),
522+ query .WithResponsePartLimitSizeBytes (partSize ),
523+ )
524+ if err != nil {
525+ return err
526+ }
527+
528+ rowCount := 0
529+ for {
530+ _ , err = rs .NextRow (scope .Ctx )
531+ if errors .Is (err , io .EOF ) {
532+ break
533+ }
534+ require .NoError (t , err )
535+ rowCount ++
536+ }
537+ require .Equal (t , targetCount , rowCount )
538+
539+ partCount = readPartCount - oldParts
540+ return nil
541+ })
542+
543+ require .NoError (t , err )
544+ return partCount
545+ }
546+
547+ partsWithBigSize := getPartCount (1000000 )
548+ partsWithLittleSize := getPartCount (100 )
549+
550+ require .Equal (t , 1 , partsWithBigSize )
551+ require .Greater (t , partsWithLittleSize , 1 )
552+ }
0 commit comments