Skip to content

Commit 50b9184

Browse files
authored
Merge pull request #361 from zinal/SQL.md-b1
Sql.md b1
2 parents 0b1ca60 + c22ecc5 commit 50b9184

File tree

1 file changed

+79
-57
lines changed

1 file changed

+79
-57
lines changed

SQL.md

Lines changed: 79 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
# `database/sql` driver for `YDB`
22

3-
Package `ydb-go-sdk` provides usage `database/sql` API also.
4-
`database/sql` driver implementation use `ydb-go-sdk` native driver API's.
3+
In addition to native YDB Go driver APIs, package `ydb-go-sdk` provides standard APIs for `database/sql`.
4+
It allows to use "regular" Go facilities to access YDB databases.
5+
Behind the scene, `database/sql` APIs are implemented using the native interfaces.
6+
57

68
## Table of contents
79
1. [Initialization of `database/sql` driver](#init)
810
* [Configure driver with `ydb.Connector` (recommended way)](#init-connector)
9-
* [Configure driver only with data source name (connection string)](#init-dsn)
10-
2. [About session pool](#session-pool)
11-
3. [Execute queries](#queries)
12-
* [On database object](#queries-db)
13-
* [With transaction](#queries-tx)
11+
* [Configure driver with data source name or connection string](#init-dsn)
12+
2. [Session pooling](#session-pool)
13+
3. [Query execution](#queries)
14+
* [Queries on database object](#queries-db)
15+
* [Queries on transaction object](#queries-tx)
1416
4. [Query modes (DDL, DML, DQL, etc.)](#query-modes)
15-
5. [Retry helpers for `YDB` `database/sql` driver](#retry)
16-
* [Over `sql.Conn` object](#retry-conn)
17-
* [Over `sql.Tx`](#retry-tx)
18-
6. [Query args types](#arg-types)
19-
7. [Get native driver from `*sql.DB`](#unwrap)
17+
5. [Changing the transaction control mode](#tx-control)
18+
6. [Retry helpers for `YDB` `database/sql` driver](#retry)
19+
* [Retries over `sql.Conn` object](#retry-conn)
20+
* [Retries over `sql.Tx`](#retry-tx)
21+
7. [Specifying query parameters](#arg-types)
22+
8. [Accessing the native driver from `*sql.DB`](#unwrap)
2023

2124
## Initialization of `database/sql` driver <a name="init"></a>
2225

@@ -43,7 +46,8 @@ func main() {
4346
db := sql.OpenDB(connector)
4447
}
4548
```
46-
### Configure driver only with data source name (connection string) <a name="init-dsn"></a>
49+
50+
### Configure driver with data source name or connection string <a name="init-dsn"></a>
4751
```go
4852
import (
4953
_ "github.com/ydb-platform/ydb-go-sdk/v3"
@@ -58,23 +62,24 @@ Data source name parameters:
5862
* static credentials with authority part of URI, like `grpcs://root:password@localhost:2135/local`
5963
* `query_mode=scripting` - you can redefine default [DML](https://en.wikipedia.org/wiki/Data_manipulation_language) query mode
6064

61-
## About session pool <a name="session-pool"></a>
65+
## Session pooling <a name="session-pool"></a>
6266

63-
Native driver `ydb-go-sdk/v3` implements internal session pool, which uses with `db.Table().Do()` or `db.Table().DoTx()` methods.
64-
Internal session pool configures with options like `ydb.WithSessionPoolSizeLimit()` and other.
65-
Unlike session pool in native driver, `database/sql` contains another session pool, which configures with `*sql.DB.SetMaxOpenConns` and `*sql.DB.SetMaxIdleConns`.
66-
Lifetime of `YDB` session depends on driver configuration and predefined errors, such as `sql.driver.ErrBadConn`.
67-
`YDB` driver for `database/sql` transform internal `YDB` errors into `sql.driver.ErrBadConn` depending on result of internal error check (delete session on error or not and other).
68-
In most cases this behaviour of `database/sql` driver implementation for specific RDBMS completes queries without result errors.
69-
But some errors on unfortunate cases may be get on client-side.
70-
That's why querying must be wrapped with retry helpers, such as `retry.Do` or `retry.DoTx` (see more about retry helpers in [retry section](#retry)).
67+
Native driver `ydb-go-sdk/v3` implements the internal session pool, which uses with `db.Table().Do()` or `db.Table().DoTx()` methods.
68+
Internal session pool is configured with options like `ydb.WithSessionPoolSizeLimit()` and other.
69+
Unlike the session pool in the native driver, `database/sql` contains a different implementation of the session pool, which is configured with `*sql.DB.SetMaxOpenConns` and `*sql.DB.SetMaxIdleConns`.
70+
Lifetime of a `YDB` session depends on driver configuration and error occurance, such as `sql.driver.ErrBadConn`.
71+
`YDB` driver for `database/sql` includes the logic to transform the internal `YDB` error codes into `sql.driver.ErrBadConn` and other retryable and non-retryable error types.
7172

72-
## Execute queries <a name="queries"></a>
73+
In most cases the implementation of `database/sql` driver for YDB allows to complete queries without user-visible errors.
74+
But some errors need to be handled on the client side, by re-running not a single operation, but a complete transaction.
75+
Therefore the transaction logic needs to be wrapped with retry helpers, such as `retry.Do` or `retry.DoTx` (see more about retry helpers in the [retry section](#retry)).
7376

74-
### On database object <a name="queries-db"></a>
77+
## Query execution <a name="queries"></a>
78+
79+
### Queries on database object <a name="queries-db"></a>
7580
```go
7681
rows, err := db.QueryContext(ctx,
77-
"SELECT series_id, title, release_date FROM /full/path/of/table/series;"
82+
"SELECT series_id, title, release_date FROM `/full/path/of/table/series`;"
7883
)
7984
if err != nil {
8085
log.Fatal(err)
@@ -97,19 +102,23 @@ if err = rows.Err(); err != nil { // always check final rows err
97102
}
98103
```
99104

100-
### With transaction <a name="queries-tx"></a>
101-
Supports only `default` transaction options which mapped to `YDB` `SerializableReadWrite` transaction settings.
105+
### Queries on transaction object <a name="queries-tx"></a>
106+
Query execution on transaction object supports only `default` transaction options
107+
which are mapped to `YDB` `SerializableReadWrite` transaction settings.
108+
109+
`YDB`'s `OnlineReadOnly` and `StaleReadOnly` transaction settings are not compatible
110+
with interactive transactions such as `database/sql`'s `*sql.Tx`.
111+
That's why `ydb-go-sdk` implements read-only `sql.LevelSnapshot` with fake transaction
112+
(temporary, until `YDB` starts to support true snapshot isolation mode).
102113

103-
`YDB`'s `OnlineReadOnly` and `StaleReadOnly` transaction settings are not compatible with interactive transactions such as `database/sql`'s `*sql.Tx`.
104-
That's why `ydb-go-sdk` implements read-only `sql.LevelSnapshot` with fake transaction (temporary, while `YDB` main clusters are supports true snapshot isolation mode)
105114
```go
106115
tx, err := db.BeginTx(ctx, sql.TxOptions{})
107116
if err != nil {
108117
log.Fatal(err)
109118
}
110119
defer tx.Rollback()
111120
rows, err := tx.QueryContext(ctx,
112-
"SELECT series_id, title, release_date FROM /full/path/of/table/series;"
121+
"SELECT series_id, title, release_date FROM `/full/path/of/table/series`;"
113122
)
114123
if err != nil {
115124
log.Fatal(err)
@@ -134,48 +143,56 @@ if err = tx.Commit(); err != nil {
134143
log.Fatal(err)
135144
}
136145
```
146+
137147
## Query modes (DDL, DML, DQL, etc.) <a name="query-modes"></a>
138-
The `YDB` server API is currently requires to select a specific method by specific request type. For example, [DDL](https://en.wikipedia.org/wiki/Data_definition_language) must be called with `table.session.ExecuteSchemeQuery`, [DML](https://en.wikipedia.org/wiki/Data_manipulation_language) must be called with `table.session.Execute`, [DQL](https://en.wikipedia.org/wiki/Data_query_language) may be called with `table.session.Execute` or `table.session.StreamExecuteScanQuery` etc. `YDB` have a `scripting` service also, which provides different query types with single method, but not supports transactions.
148+
Currently the `YDB` server APIs require the use of a proper GRPC service method depending on the specific request type.
149+
In particular, [DDL](https://en.wikipedia.org/wiki/Data_definition_language) must be called through `table.session.ExecuteSchemeQuery`,
150+
[DML](https://en.wikipedia.org/wiki/Data_manipulation_language) needs `table.session.Execute`, and
151+
[DQL](https://en.wikipedia.org/wiki/Data_query_language) should be passed via `table.session.Execute` or `table.session.StreamExecuteScanQuery`.
152+
`YDB` also has a so-called "scripting" service, which supports different query types within a single method,
153+
but without support for transactions.
139154

140-
That's why needs to select query mode on client side currently.
155+
Unfortunately, this leads to the need to choose the proper query mode on the application side.
141156

142-
`YDB` team have a roadmap goal to implements a single method for executing different query types.
157+
`YDB` team has a roadmap goal to implement a single universal service method for executing
158+
different query types and without the limitations of the "scripting" service method.
143159

144-
`database/sql` driver implementation for `YDB` supports next query modes:
160+
`database/sql` driver implementation for `YDB` supports the following query modes:
145161
* `ydb.DataQueryMode` - default query mode, for lookup [DQL](https://en.wikipedia.org/wiki/Data_query_language) queries and [DML](https://en.wikipedia.org/wiki/Data_manipulation_language) queries.
146-
* `ydb.ExplainQueryMode` - for gettting plan and [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of some query
147-
* `ydb.ScanQueryMode` - for strong [OLAP](https://en.wikipedia.org/wiki/Online_analytical_processing) scenarious, [DQL-only](https://en.wikipedia.org/wiki/Data_query_language) queries. Read more about scan queries in [ydb.tech](https://ydb.tech/en/docs/concepts/scan_query)
162+
* `ydb.ExplainQueryMode` - for gettting plan and [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of the query
163+
* `ydb.ScanQueryMode` - for heavy [OLAP](https://en.wikipedia.org/wiki/Online_analytical_processing) style scenarious, with [DQL-only](https://en.wikipedia.org/wiki/Data_query_language) queries. Read more about scan queries in [ydb.tech](https://ydb.tech/en/docs/concepts/scan_query)
148164
* `ydb.SchemeQueryMode` - for [DDL](https://en.wikipedia.org/wiki/Data_definition_language) queries
149-
* `ydb.ScriptingQueryMode` - for [DDL](https://en.wikipedia.org/wiki/Data_definition_language), [DML](https://en.wikipedia.org/wiki/Data_manipulation_language), [DQL](https://en.wikipedia.org/wiki/Data_query_language) queries (not a [TCL](https://en.wikipedia.org/wiki/SQL#Transaction_controls)). Be careful: queries executes longer than with other query modes and consumes bigger server-side resources
165+
* `ydb.ScriptingQueryMode` - for [DDL](https://en.wikipedia.org/wiki/Data_definition_language), [DML](https://en.wikipedia.org/wiki/Data_manipulation_language), [DQL](https://en.wikipedia.org/wiki/Data_query_language) queries (not a [TCL](https://en.wikipedia.org/wiki/SQL#Transaction_controls)). Be careful: queries execute longer than with other query modes, and consume more server-side resources
150166

151-
Example for changing default query mode:
167+
Example for changing the default query mode:
152168
```go
153169
res, err = db.ExecContext(ydb.WithQueryMode(ctx, ydb.SchemeQueryMode),
154170
"DROP TABLE `/full/path/to/table/series`",
155171
)
156172
```
157173

158-
## Specify `YDB` transaction control <a name="tx-control"></a>
174+
## Changing the transaction control mode <a name="tx-control"></a>
159175

160-
Default `YDB`'s transaction control is a `SerializableReadWrite`.
161-
Default transaction control outside interactive transactions may be changed with context:
176+
Default `YDB`'s transaction control mode is a `SerializableReadWrite`.
177+
Default transaction control mode can be changed outside of interactive transactions by updating the context object:
162178
```
163179
ctx := ydb.WithTxControl(ctx, table.OnlineReadOnlyTxControl())
164180
```
165181

166182
## Retry helpers for `YDB` `database/sql` driver <a name="retry"></a>
167183

168184
`YDB` is a distributed `RDBMS` with non-stop 24/7 releases flow.
169-
It means some nodes may be not available for queries.
170-
Also network errors may be occurred.
171-
That's why some queries may be complete with errors.
185+
It means some nodes may be unavailable for queries at some point in time.
186+
Network errors may also occur.
187+
That's why some queries may complete with errors.
172188
Most of those errors are transient.
173-
`ydb-go-sdk`'s "knows" what to do on specific error: retry or not, with or without backoff, with or whithout deleting session, etc.
174-
`ydb-go-sdk` provides retry helpers which can work either with plain database connection object, or with interactive transaction object.
189+
`ydb-go-sdk`'s "knows" what to do on specific error: retry or not, with or without backoff, with or without the need to re-establish the session, etc.
190+
`ydb-go-sdk` provides retry helpers which can work either with the database connection object, or with the transaction object.
175191

176-
### Over `sql.Conn` object <a name="retry-conn"></a>
192+
### Retries over `sql.Conn` object <a name="retry-conn"></a>
177193

178-
`retry.Do` helper allow custom lambda, which must return error for processing or nil if retry operation is ok.
194+
`retry.Do` helper accepts custom lambda, which must return error if it happens during the processing,
195+
or nil if the operation succeeds.
179196
```
180197
import (
181198
"github.com/ydb-platform/ydb-go-sdk/v3/retry"
@@ -193,11 +210,15 @@ err := retry.Do(context.TODO(), db, func(ctx context.Context, cc *sql.Conn) erro
193210
194211
```
195212

196-
### Over `sql.Tx` <a name="retry-tx"></a>
213+
### Retries over `sql.Tx` <a name="retry-tx"></a>
214+
215+
`retry.DoTx` helper accepts custom lambda, which must return error if it happens during processing,
216+
or nil if the operation succeeds.
197217

198-
`retry.DoTx` helper allow custom lambda, which must return error for processing or nil if retry operation is ok.
218+
`tx` object is a prepared transaction object.
219+
220+
The logic within the custom lambda does not need the explicit commit or rollback at the end - `retry.DoTx` does it automatically.
199221

200-
`tx` object is a prepared transaction object which not requires commit or rollback at the end - `retry.DoTx` do it automatically.
201222
```
202223
import (
203224
"github.com/ydb-platform/ydb-go-sdk/v3/retry"
@@ -219,10 +240,10 @@ err := retry.DoTx(context.TODO(), db, func(ctx context.Context, tx *sql.Tx) erro
219240
}))
220241
```
221242

222-
## Query args types <a name="arg-types"></a>
243+
## Specifying query parameters <a name="arg-types"></a>
223244

224-
`database/sql` driver for `YDB` supports next types of query args:
225-
* multiple `sql.NamedArg` (uniform `database/sql` arg)
245+
`database/sql` driver for `YDB` supports the following types of query parameters:
246+
* multiple `sql.NamedArg` arguments (standard `database/sql` query parameters)
226247
```
227248
rows, err := cc.QueryContext(ctx, `
228249
DECLARE $seasonTitle AS Utf8;
@@ -233,7 +254,7 @@ err := retry.DoTx(context.TODO(), db, func(ctx context.Context, tx *sql.Tx) erro
233254
sql.Named("views", uint64(1000)),
234255
)
235256
```
236-
* multiple native for `ydb-go-sdk` `table.ParameterOption` which constructs from `table.ValueParam("name", value)`
257+
* multiple native `ydb-go-sdk` `table.ParameterOption` arguments which are constructed with `table.ValueParam("name", value)`
237258
```
238259
rows, err := cc.QueryContext(ctx, `
239260
DECLARE $seasonTitle AS Utf8;
@@ -244,7 +265,7 @@ err := retry.DoTx(context.TODO(), db, func(ctx context.Context, tx *sql.Tx) erro
244265
table.ValueParam("views", types.Uint64Value((1000)),
245266
)
246267
```
247-
* single native for `ydb-go-sdk` `*table.QueryParameters` which constructs from `table.NewQueryParameters(parameterOptions...)`
268+
* single native `ydb-go-sdk` `*table.QueryParameters` argument which are constructed with `table.NewQueryParameters(parameterOptions...)`
248269
```
249270
rows, err := cc.QueryContext(ctx, `
250271
DECLARE $seasonTitle AS Utf8;
@@ -257,7 +278,8 @@ err := retry.DoTx(context.TODO(), db, func(ctx context.Context, tx *sql.Tx) erro
257278
),
258279
)
259280
```
260-
## Get native driver from `*sql.DB` <a name="unwrap"></a>
281+
282+
## Accessing the native driver from `*sql.DB` <a name="unwrap"></a>
261283

262284
```
263285
db, err := sql.Open("ydb", "grpcs://localhost:2135/local")

0 commit comments

Comments
 (0)