github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/query/execute_query.go (about) 1 package query 2 3 import ( 4 "context" 5 "io" 6 "time" 7 8 "github.com/ydb-platform/ydb-go-genproto/Ydb_Query_V1" 9 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Operations" 10 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Query" 11 "google.golang.org/grpc" 12 "google.golang.org/protobuf/types/known/durationpb" 13 14 "github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator" 15 "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" 16 "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" 17 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" 18 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" 19 "github.com/ydb-platform/ydb-go-sdk/v3/query" 20 "github.com/ydb-platform/ydb-go-sdk/v3/retry" 21 "github.com/ydb-platform/ydb-go-sdk/v3/table/stats" 22 ) 23 24 type executeSettings interface { 25 ExecMode() options.ExecMode 26 StatsMode() options.StatsMode 27 StatsCallback() func(stats stats.QueryStats) 28 TxControl() *query.TransactionControl 29 Syntax() options.Syntax 30 Params() *params.Parameters 31 CallOptions() []grpc.CallOption 32 RetryOpts() []retry.Option 33 ResourcePool() string 34 } 35 36 type executeScriptConfig interface { 37 executeSettings 38 39 ResultsTTL() time.Duration 40 OperationParams() *Ydb_Operations.OperationParams 41 } 42 43 func executeQueryScriptRequest(a *allocator.Allocator, q string, cfg executeScriptConfig) ( 44 *Ydb_Query.ExecuteScriptRequest, 45 []grpc.CallOption, 46 ) { 47 request := &Ydb_Query.ExecuteScriptRequest{ 48 OperationParams: &Ydb_Operations.OperationParams{ 49 OperationMode: 0, 50 OperationTimeout: nil, 51 CancelAfter: nil, 52 Labels: nil, 53 ReportCostInfo: 0, 54 }, 55 ExecMode: Ydb_Query.ExecMode(cfg.ExecMode()), 56 ScriptContent: queryQueryContent(a, Ydb_Query.Syntax(cfg.Syntax()), q), 57 Parameters: cfg.Params().ToYDB(a), 58 StatsMode: Ydb_Query.StatsMode(cfg.StatsMode()), 59 ResultsTtl: durationpb.New(cfg.ResultsTTL()), 60 PoolId: cfg.ResourcePool(), 61 } 62 63 return request, cfg.CallOptions() 64 } 65 66 func executeQueryRequest(a *allocator.Allocator, sessionID, q string, cfg executeSettings) ( 67 *Ydb_Query.ExecuteQueryRequest, 68 []grpc.CallOption, 69 ) { 70 request := a.QueryExecuteQueryRequest() 71 72 request.SessionId = sessionID 73 request.ExecMode = Ydb_Query.ExecMode(cfg.ExecMode()) 74 request.TxControl = cfg.TxControl().ToYDB(a) 75 request.Query = queryFromText(a, q, Ydb_Query.Syntax(cfg.Syntax())) 76 request.Parameters = cfg.Params().ToYDB(a) 77 request.StatsMode = Ydb_Query.StatsMode(cfg.StatsMode()) 78 request.ConcurrentResultSets = false 79 request.PoolId = cfg.ResourcePool() 80 81 return request, cfg.CallOptions() 82 } 83 84 func queryQueryContent(a *allocator.Allocator, syntax Ydb_Query.Syntax, q string) *Ydb_Query.QueryContent { 85 content := a.QueryQueryContent() 86 content.Syntax = syntax 87 content.Text = q 88 89 return content 90 } 91 92 func queryFromText( 93 a *allocator.Allocator, q string, syntax Ydb_Query.Syntax, 94 ) *Ydb_Query.ExecuteQueryRequest_QueryContent { 95 content := a.QueryExecuteQueryRequestQueryContent() 96 content.QueryContent = queryQueryContent(a, syntax, q) 97 98 return content 99 } 100 101 func execute( 102 ctx context.Context, sessionID string, c Ydb_Query_V1.QueryServiceClient, 103 q string, settings executeSettings, opts ...resultOption, 104 ) ( 105 _ *streamResult, finalErr error, 106 ) { 107 a := allocator.New() 108 defer a.Free() 109 110 request, callOptions := executeQueryRequest(a, sessionID, q, settings) 111 112 executeCtx := xcontext.ValueOnly(ctx) 113 114 stream, err := c.ExecuteQuery(executeCtx, request, callOptions...) 115 if err != nil { 116 return nil, xerrors.WithStackTrace(err) 117 } 118 119 r, err := newResult(ctx, stream, append(opts, withStatsCallback(settings.StatsCallback()))...) 120 if err != nil { 121 return nil, xerrors.WithStackTrace(err) 122 } 123 124 return r, nil 125 } 126 127 func readAll(ctx context.Context, r *streamResult) error { 128 defer func() { 129 _ = r.Close(ctx) 130 }() 131 132 for { 133 _, err := r.nextResultSet(ctx) 134 if err != nil { 135 if xerrors.Is(err, io.EOF) { 136 return nil 137 } 138 139 return xerrors.WithStackTrace(err) 140 } 141 } 142 } 143 144 func readResultSet(ctx context.Context, r *streamResult) (_ *resultSetWithClose, finalErr error) { 145 rs, err := r.nextResultSet(ctx) 146 if err != nil { 147 return nil, xerrors.WithStackTrace(err) 148 } 149 150 _, err = r.nextResultSet(ctx) 151 if err == nil { 152 return nil, xerrors.WithStackTrace(errMoreThanOneResultSet) 153 } 154 if !xerrors.Is(err, io.EOF) { 155 return nil, xerrors.WithStackTrace(err) 156 } 157 158 return &resultSetWithClose{ 159 resultSet: rs, 160 close: r.Close, 161 }, nil 162 } 163 164 func readMaterializedResultSet(ctx context.Context, r *streamResult) (_ *materializedResultSet, finalErr error) { 165 defer func() { 166 _ = r.Close(ctx) 167 }() 168 169 rs, err := r.nextResultSet(ctx) 170 if err != nil { 171 return nil, xerrors.WithStackTrace(err) 172 } 173 174 var rows []query.Row 175 for { 176 row, err := rs.nextRow(ctx) 177 if err != nil { 178 if xerrors.Is(err, io.EOF) { 179 break 180 } 181 182 return nil, xerrors.WithStackTrace(err) 183 } 184 185 rows = append(rows, row) 186 } 187 188 _, err = r.nextResultSet(ctx) 189 if err == nil { 190 return nil, xerrors.WithStackTrace(errMoreThanOneResultSet) 191 } 192 if !xerrors.Is(err, io.EOF) { 193 return nil, xerrors.WithStackTrace(err) 194 } 195 196 return MaterializedResultSet(rs.Index(), rs.Columns(), rs.ColumnTypes(), rows), nil 197 } 198 199 func readRow(ctx context.Context, r *streamResult) (_ *Row, finalErr error) { 200 defer func() { 201 _ = r.Close(ctx) 202 }() 203 204 rs, err := r.nextResultSet(ctx) 205 if err != nil { 206 return nil, xerrors.WithStackTrace(err) 207 } 208 209 row, err := rs.nextRow(ctx) 210 if err != nil { 211 return nil, xerrors.WithStackTrace(err) 212 } 213 214 _, err = rs.nextRow(ctx) 215 if err == nil { 216 return nil, xerrors.WithStackTrace(errMoreThanOneRow) 217 } 218 if !xerrors.Is(err, io.EOF) { 219 return nil, xerrors.WithStackTrace(err) 220 } 221 222 _, err = r.NextResultSet(ctx) 223 if err == nil { 224 return nil, xerrors.WithStackTrace(errMoreThanOneResultSet) 225 } 226 if !xerrors.Is(err, io.EOF) { 227 return nil, xerrors.WithStackTrace(err) 228 } 229 230 return row, nil 231 }