Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
* Supported `sql.Null*` from `database/sql` as query params in `toValue` func
* Added `WithConcurrentResultSets` option for `db.Query().Query()`

## v3.118.0
* Added support for nullable `Date32`, `Datetime64`, `Timestamp64`, and `Interval64` types in the `optional` parameter builder
Expand Down
1 change: 1 addition & 0 deletions internal/query/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ func clientQuery(ctx context.Context, pool sessionPool, q string, opts ...option
if err != nil {
return xerrors.WithStackTrace(err)
}

defer func() {
_ = streamResult.Close(ctx)
}()
Expand Down
18 changes: 18 additions & 0 deletions internal/query/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,24 @@ func TestClient(t *testing.T) {
Status: Ydb.StatusIds_SUCCESS,
ResultSetIndex: 0,
ResultSet: &Ydb.ResultSet{
Columns: []*Ydb.Column{
{
Name: "a",
Type: &Ydb.Type{
Type: &Ydb.Type_TypeId{
TypeId: Ydb.Type_UINT64,
},
},
},
{
Name: "b",
Type: &Ydb.Type{
Type: &Ydb.Type_TypeId{
TypeId: Ydb.Type_UTF8,
},
},
},
},
Rows: []*Ydb.Value{
{
Items: []*Ydb.Value{{
Expand Down
3 changes: 2 additions & 1 deletion internal/query/execute_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type executeSettings interface {
ResourcePool() string
ResponsePartLimitSizeBytes() int64
Label() string
ConcurrentResultSets() bool
}

type executeScriptConfig interface {
Expand Down Expand Up @@ -92,7 +93,7 @@ func executeQueryRequest(sessionID, q string, cfg executeSettings) (
},
Parameters: params,
StatsMode: Ydb_Query.StatsMode(cfg.StatsMode()),
ConcurrentResultSets: false,
ConcurrentResultSets: cfg.ConcurrentResultSets(),
PoolId: cfg.ResourcePool(),
ResponsePartLimitBytes: cfg.ResponsePartLimitSizeBytes(),
}
Expand Down
18 changes: 17 additions & 1 deletion internal/query/options/execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type (
issueCallback func(issues []*Ydb_Issue.IssueMessage)
responsePartLimitBytes int64
label string
concurrentResultSets bool
}

// Execute is an interface for execute method options
Expand All @@ -72,9 +73,12 @@ type (
}
execModeOption = ExecMode
responsePartLimitBytes int64
issuesOption struct {

issuesOption struct {
callback func([]*Ydb_Issue.IssueMessage)
}

concurrentResultSets bool
)

func (poolID resourcePool) applyExecuteOption(s *executeSettings) {
Expand Down Expand Up @@ -132,6 +136,10 @@ func (opts issuesOption) applyExecuteOption(s *executeSettings) {
s.issueCallback = opts.callback
}

func (opt concurrentResultSets) applyExecuteOption(s *executeSettings) {
s.concurrentResultSets = bool(opt)
}

const (
ExecModeParse = ExecMode(Ydb_Query.ExecMode_EXEC_MODE_PARSE)
ExecModeValidate = ExecMode(Ydb_Query.ExecMode_EXEC_MODE_VALIDATE)
Expand Down Expand Up @@ -205,6 +213,10 @@ func (s *executeSettings) Label() string {
return s.label
}

func (s *executeSettings) ConcurrentResultSets() bool {
return s.concurrentResultSets
}

func WithParameters(params params.Parameters) parametersOption {
return parametersOption{
params: params,
Expand Down Expand Up @@ -237,6 +249,10 @@ func WithResponsePartLimitSizeBytes(size int64) responsePartLimitBytes {
return responsePartLimitBytes(size)
}

func WithConcurrentResultSets(isEnabled bool) concurrentResultSets {
return concurrentResultSets(isEnabled)
}

func (size responsePartLimitBytes) applyExecuteOption(s *executeSettings) {
s.responsePartLimitBytes = int64(size)
}
Expand Down
57 changes: 42 additions & 15 deletions internal/query/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
"time"

"github.com/ydb-platform/ydb-go-genproto/Ydb_Query_V1"
"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
"github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Issue"
"github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Query"

"github.com/ydb-platform/ydb-go-sdk/v3/internal/query/result"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/stack"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/stats"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/types"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xiter"
"github.com/ydb-platform/ydb-go-sdk/v3/query"
Expand Down Expand Up @@ -433,34 +435,59 @@
return MaterializedResultSet(rs.Index(), rs.Columns(), rs.ColumnTypes(), rows), nil
}

func resultToMaterializedResult(ctx context.Context, r result.Result) (result.Result, error) {
var resultSets []result.Set
func resultToMaterializedResult(ctx context.Context, r *streamResult) (result.Result, error) {
type resultSet struct {
rows []query.Row
columns []*Ydb.Column
}
resultSetByIndex := make(map[int64]resultSet)

for {
rs, err := r.NextResultSet(ctx)
if ctx.Err() != nil {
return nil, xerrors.WithStackTrace(ctx.Err())
}
if r.closer.Err() != nil {
return nil, xerrors.WithStackTrace(r.closer.Err())
}

rs := resultSetByIndex[r.lastPart.GetResultSetIndex()]
if len(rs.columns) == 0 {
rs.columns = r.lastPart.GetResultSet().GetColumns()
}

rows := make([]query.Row, len(r.lastPart.GetResultSet().GetRows()))
for i := range r.lastPart.GetResultSet().GetRows() {
rows[i] = NewRow(rs.columns, r.lastPart.GetResultSet().GetRows()[i])
}
rs.rows = append(rs.rows, rows...)

resultSetByIndex[r.lastPart.GetResultSetIndex()] = rs

var err error
r.lastPart, err = r.nextPart(ctx)
if err != nil {
if xerrors.Is(err, io.EOF) {
break
}

return nil, xerrors.WithStackTrace(err)
}
if r.lastPart.GetExecStats() != nil && r.statsCallback != nil {
r.statsCallback(stats.FromQueryStats(r.lastPart.GetExecStats()))
}
}

var rows []query.Row
for {
row, err := rs.NextRow(ctx)
if err != nil {
if xerrors.Is(err, io.EOF) {
break
}

return nil, xerrors.WithStackTrace(err)
}
resultSets := make([]result.Set, len(resultSetByIndex))
for rsIndex, rs := range resultSetByIndex {
columnNames := make([]string, len(rs.columns))
columnTypes := make([]types.Type, len(rs.columns))

rows = append(rows, row)
for i := range rs.columns {
columnNames[i] = rs.columns[i].Name

Check failure on line 486 in internal/query/result.go

View workflow job for this annotation

GitHub Actions / golangci-lint

avoid direct access to proto field rs.columns[i].Name, use rs.columns[i].GetName() instead (protogetter)
columnTypes[i] = types.TypeFromYDB(rs.columns[i].Type)

Check failure on line 487 in internal/query/result.go

View workflow job for this annotation

GitHub Actions / golangci-lint

avoid direct access to proto field rs.columns[i].Type, use rs.columns[i].GetType() instead (protogetter)
}

resultSets = append(resultSets, MaterializedResultSet(rs.Index(), rs.Columns(), rs.ColumnTypes(), rows))
resultSets[rsIndex] = MaterializedResultSet(int(rsIndex), columnNames, columnTypes, rs.rows)
}

return &materializedResult{
Expand Down
4 changes: 4 additions & 0 deletions query/execute_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ func WithResponsePartLimitSizeBytes(size int64) ExecuteOption {
return options.WithResponsePartLimitSizeBytes(size)
}

func WithConcurrentResultSets(isEnabled bool) ExecuteOption {
return options.WithConcurrentResultSets(isEnabled)
}

func WithCallOptions(opts ...grpc.CallOption) ExecuteOption {
return options.WithCallOptions(opts...)
}
Expand Down
Loading