66 "time"
77
88 "github.com/ydb-platform/ydb-go-sdk/v3"
9+ "github.com/ydb-platform/ydb-go-sdk/v3/query"
910)
1011
1112// author: Egor Danilov
@@ -32,12 +33,11 @@ func main() {
3233 queryCtx , txCancel := context .WithTimeout (context .Background (), 30 * time .Second )
3334 defer txCancel ()
3435
35- // Ниже представлены примеры по обращению к клиенту для выполнения YQL запросов
36- //
36+ // Ниже представлены примеры по обращению к клиенту для выполнения YQL запросов.
3737 // Query(), QueryResultSet() и QueryRow() являются хелперами для неинтерактивных транзакций
38- // (т.е. когда транзакция завершается за одно обращение к серверу)
39- // Ретраи тут происходят внутри, а наружу возвращается уже материализированный в памяти в результат,
40- // Таймаутом транзакции можно управлять через контекст
38+ // (т.е. когда транзакция завершается за одно обращение к серверу).
39+ // Ретраи тут происходят внутри, а наружу возвращается уже материализированный в памяти в результат.
40+ // Таймаутом транзакции можно управлять через контекст.
4141
4242 result , err := db .Query ().Query (queryCtx , "SELECT 1 as id" )
4343 if err != nil {
@@ -90,4 +90,54 @@ func main() {
9090 log .Fatal (err )
9191 }
9292 println (structId .Id )
93+
94+ // ======
95+
96+ // Ниже представлен код для отправки запроса. Он же используется в реализации методов-хелперов, показанных выше.
97+ // В [query.Client.Do] передается анонимная функция, которая будет ретраиться.
98+ // По типу ошибки, которую вернет эта анонимная функция, драйвер решит, надо ли ретраить запрос.
99+ err = db .Query ().Do (
100+ queryCtx ,
101+ // Внутри анонимной функции получаем из пула сессию query.Session для выполнения запроса.
102+ // После окончания работы ретраера сессия возвращается обратно в пул.
103+ func (ctx context.Context , s query.Session ) error {
104+ res , err := s .Query (ctx , "SELECT 4 as id;" )
105+
106+ if err != nil {
107+ return err
108+ }
109+
110+ defer func () { _ = res .Close (ctx ) }()
111+
112+ // Итерируемся по набору результатов
113+ for rs , err := range res .ResultSets (ctx ) {
114+ if err != nil {
115+ return err
116+ }
117+
118+ // Итерируемся по строкам в каждом наборе результате
119+ for row , err := range rs .Rows (ctx ) {
120+ if err != nil {
121+ return err
122+ }
123+
124+ // Читаем результат
125+ // Важно - код внутри ретраера должен быть готов к тому,
126+ // что он может исполниться несколько раз подряд.
127+ // Например, нужно очищать слайс, куда будут записываться результаты,
128+ // иначе там могут оказаться дублирующиеся данные.
129+ if err = row .ScanStruct (& structId ); err != nil {
130+ return err
131+ }
132+ }
133+ }
134+ return nil
135+ },
136+ query .WithIdempotent (),
137+ )
138+ if err != nil {
139+ log .Fatal (err )
140+ }
141+
142+ println (structId .Id )
93143}
0 commit comments