@@ -70,7 +70,7 @@ func NextResultSet(ctx context.Context, poolId, connId, rowsId int64) (*spannerp
7070// as it allows the library to re-use the encoding buffer.
7171// TODO: Add an encoder function as input argument, instead of hardcoding protobuf encoding here.
7272func NextEncoded (ctx context.Context , poolId , connId , rowsId int64 ) ([]byte , error ) {
73- _ , bytes , err := next (ctx , poolId , connId , rowsId , true )
73+ _ , bytes , err := next (ctx , poolId , connId , rowsId /*marshalResult=*/ , true /*resetBuffer=*/ , false )
7474 if err != nil {
7575 return nil , err
7676 }
@@ -79,7 +79,20 @@ func NextEncoded(ctx context.Context, poolId, connId, rowsId int64) ([]byte, err
7979
8080// Next returns the next row as a protobuf ListValue.
8181func Next (ctx context.Context , poolId , connId , rowsId int64 ) (* structpb.ListValue , error ) {
82- values , _ , err := next (ctx , poolId , connId , rowsId , false )
82+ return nextWithBufferOption (ctx , poolId , connId , rowsId /*resetBuffer=*/ , true )
83+ }
84+
85+ // NextBuffered returns the next row as a protobuf ListValue.
86+ // The same buffer is used to construct the ListValue for each call. This means that this function is only
87+ // safe to call if the result that is returned is copied into a different data structure before the next call
88+ // to this function. Safe use of this function for example includes calls that request the next row and then
89+ // serialize this result into a byte slice or send it as a gRPC message (which also serializes the result).
90+ func NextBuffered (ctx context.Context , poolId , connId , rowsId int64 ) (* structpb.ListValue , error ) {
91+ return nextWithBufferOption (ctx , poolId , connId , rowsId /*resetBuffer=*/ , false )
92+ }
93+
94+ func nextWithBufferOption (ctx context.Context , poolId , connId , rowsId int64 , resetBuffer bool ) (* structpb.ListValue , error ) {
95+ values , _ , err := next (ctx , poolId , connId , rowsId /*marshalResult=*/ , false , resetBuffer )
8396 if err != nil {
8497 return nil , err
8598 }
@@ -90,7 +103,7 @@ func Next(ctx context.Context, poolId, connId, rowsId int64) (*structpb.ListValu
90103// The row is returned as a protobuf ListValue if marshalResult==false.
91104// The row is returned as a byte slice if marshalResult==true.
92105// TODO: Add generics to the function and add input arguments for encoding instead of hardcoding it.
93- func next (ctx context.Context , poolId , connId , rowsId int64 , marshalResult bool ) (* structpb.ListValue , []byte , error ) {
106+ func next (ctx context.Context , poolId , connId , rowsId int64 , marshalResult , resetBuffer bool ) (* structpb.ListValue , []byte , error ) {
94107 rows , err := findRows (poolId , connId , rowsId )
95108 if err != nil {
96109 return nil , nil , err
@@ -99,6 +112,9 @@ func next(ctx context.Context, poolId, connId, rowsId int64, marshalResult bool)
99112 if err != nil {
100113 return nil , nil , err
101114 }
115+ if resetBuffer {
116+ rows .buffer = nil
117+ }
102118 if ! marshalResult || values == nil {
103119 return values , nil , nil
104120 }
0 commit comments