|
1 | 1 | # `database/sql` driver for `YDB` |
2 | 2 |
|
3 | | -## Initialization of `database/sql` driver |
| 3 | +Package `ydb-go-sdk` provides usage `database/sql` API also. |
| 4 | +`database/sql` driver implementation use `ydb-go-sdk` native driver API's. |
4 | 5 |
|
5 | | -### Configure driver with `ydb.Connector` (recommended way) |
6 | | - ``` |
7 | | - import ( |
8 | | - "github.com/ydb-platform/ydb-go-sdk/v3" |
| 6 | +## Table of contents |
| 7 | +1. [Initialization of `database/sql` driver](#init) |
| 8 | + * [Configure driver with `ydb.Connector` (recommended way)](#init-connector) |
| 9 | + * [Configure driver only with data source name (connection string)](#init-dsn) |
| 10 | +2. [Execute queries](#queries) |
| 11 | + * [On database object](#queries-db) |
| 12 | + * [With transaction](#queries-tx) |
| 13 | +3. [Query modes (DDL, DML, DQL, etc.)](#query-modes) |
| 14 | + |
| 15 | +## Initialization of `database/sql` driver <a name="init"></a> |
| 16 | + |
| 17 | +### Configure driver with `ydb.Connector` (recommended way) <a name="init-connector"></a> |
| 18 | +```go |
| 19 | +import ( |
| 20 | + "github.com/ydb-platform/ydb-go-sdk/v3" |
| 21 | +) |
| 22 | + |
| 23 | +func main() { |
| 24 | + // init native ydb-go-sdk driver |
| 25 | + nativeDriver, err := ydb.Open(context.TODO(), "grpcs://localhost:2135/local", |
| 26 | + // See many ydb.Option's for configure driver |
9 | 27 | ) |
10 | | - |
11 | | - func main() { |
12 | | - // init native ydb-go-sdk driver |
13 | | - nativeDriver, err := ydb.Open(context.TODO(), "grpcs://localhost:2135/local", |
14 | | - // See many ydb.Option's for configure driver |
15 | | - ) |
16 | | - if err != nil { |
17 | | - // fallback on error |
18 | | - } |
19 | | - connector, err := ydb.Connector(nativeDriver, |
20 | | - // See ydb.ConnectorOption's for configure connector |
21 | | - ) |
22 | | - if err != nil { |
23 | | - // fallback on error |
24 | | - } |
25 | | - db := sql.OpenDB(connector) |
| 28 | + if err != nil { |
| 29 | + // fallback on error |
26 | 30 | } |
27 | | - ``` |
28 | | -### Configure driver only with data source name (connection string) |
29 | | - ``` |
30 | | - import ( |
31 | | - _ "github.com/ydb-platform/ydb-go-sdk/v3" |
| 31 | + connector, err := ydb.Connector(nativeDriver, |
| 32 | + // See ydb.ConnectorOption's for configure connector |
32 | 33 | ) |
33 | | - |
34 | | - func main() { |
35 | | - db, err := sql.Open("ydb", "grpcs://localhost:2135/local") |
| 34 | + if err != nil { |
| 35 | + // fallback on error |
| 36 | + } |
| 37 | + db := sql.OpenDB(connector) |
| 38 | +} |
| 39 | +``` |
| 40 | +### Configure driver only with data source name (connection string) <a name="init-dsn"></a> |
| 41 | +```go |
| 42 | +import ( |
| 43 | + _ "github.com/ydb-platform/ydb-go-sdk/v3" |
| 44 | +) |
| 45 | + |
| 46 | +func main() { |
| 47 | + db, err := sql.Open("ydb", "grpcs://localhost:2135/local") |
| 48 | +} |
| 49 | +``` |
| 50 | +Data source name parameters: |
| 51 | +* `token` – access token to be used during requests (required) |
| 52 | +* static credentials with authority part of URI, like `grpcs://root:password@localhost:2135/local` |
| 53 | +* `query_mode=scripting` - you can redefine default `data` query mode |
| 54 | + |
| 55 | +## Execute queries <a name="queries"></a> |
| 56 | + |
| 57 | +### On database object <a name="queries-db"></a> |
| 58 | +```go |
| 59 | +rows, err := db.QueryContext(ctx, |
| 60 | + "SELECT series_id, title, release_date FROM /full/path/of/table/series;" |
| 61 | +) |
| 62 | +if err != nil { |
| 63 | + log.Fatal(err) |
| 64 | +} |
| 65 | +defer rows.Close() // always close rows |
| 66 | +var ( |
| 67 | + id *string |
| 68 | + title *string |
| 69 | + releaseDate *time.Time |
| 70 | +) |
| 71 | +for rows.Next() { // iterate over rows |
| 72 | + // apply database values to go's type destinations |
| 73 | + if err = rows.Scan(&id, &title, &releaseDate); err != nil { |
| 74 | + log.Fatal(err) |
| 75 | + } |
| 76 | + log.Printf("> [%s] %s (%s)", *id, *title, releaseDate.Format("2006-01-02")) |
| 77 | +} |
| 78 | +if err = rows.Err(); err != nil { // always check final rows err |
| 79 | + log.Fatal(err) |
| 80 | +} |
| 81 | + |
| 82 | +``` |
| 83 | + |
| 84 | +### With transaction <a name="queries-tx"></a> |
| 85 | +Supports only `default` transaction options which mapped to `YDB`'s `SerializableReadWrite` transaction settings. |
| 86 | +`YDB`'s `OnlineReadOnly` and `StaleReadOnly` transaction settings are not compatible with interactive transactions such as `database/sql`'s `*sql.Tx`. |
| 87 | +`YDB`'s `OnlineReadOnly` and `StaleReadOnly` transaction settings can be explicitly applied to each query outside interactive transaction (see more in [Isolation levels support](#tx-control)) |
| 88 | +``` |
| 89 | +tx, err := db.BeginTx(ctx, sql.TxOptions{}) |
| 90 | +if err != nil { |
| 91 | + log.Fatal(err) |
| 92 | +} |
| 93 | +defer tx.Rollback() |
| 94 | +rows, err := tx.QueryContext(ctx, |
| 95 | + "SELECT series_id, title, release_date FROM /full/path/of/table/series;" |
| 96 | +) |
| 97 | +if err != nil { |
| 98 | + log.Fatal(err) |
| 99 | +} |
| 100 | +defer rows.Close() // always close rows |
| 101 | +var ( |
| 102 | + id *string |
| 103 | + title *string |
| 104 | + releaseDate *time.Time |
| 105 | +) |
| 106 | +for rows.Next() { // iterate over rows |
| 107 | + // apply database values to go's type destinations |
| 108 | + if err = rows.Scan(&id, &title, &releaseDate); err != nil { |
| 109 | + log.Fatal(err) |
36 | 110 | } |
37 | | - ``` |
38 | | - Data source name parameters: |
39 | | - * `token` – access token to be used during requests (required) |
40 | | - * static credentials with authority part of URI, like `grpcs://root:password@localhost:2135/local` |
41 | | - * `query_mode=scripting` - you can redefine default `data` query mode |
| 111 | + log.Printf("> [%s] %s (%s)", *id, *title, releaseDate.Format("2006-01-02")) |
| 112 | +} |
| 113 | +if err = rows.Err(); err != nil { // always check final rows err |
| 114 | + log.Fatal(err) |
| 115 | +} |
| 116 | +if err = tx.Commit(); err != nil { |
| 117 | + log.Fatal(err) |
| 118 | +} |
| 119 | +``` |
| 120 | +## Query modes (DDL, DML, DQL, etc.) <a name="query-modes"></a> |
| 121 | +The `YDB` server API is currently requires to select a specific method by specific request type. For example, `DDL` must be called with `table.session.ExecuteSchemeQuery`, `DML` must be called with `table.session.Execute`, `DQL` 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. |
42 | 122 |
|
43 | | -## Execute queries |
| 123 | +Thats why needs to select query mode on client side currently. |
44 | 124 |
|
45 | | -### On database object |
| 125 | +`YDB` team have a roadmap goal to implements a single method for executing different query types. |
46 | 126 |
|
47 | | -### With transaction |
| 127 | +`database/sql` driver implementation for `YDB` supports next query modes: |
| 128 | +* `ydb.DataQueryMode` - default query mode, for lookup `DQL` queries and `DML` queries. |
| 129 | +* `ydb.ExplainQueryMode` - for gettting plan and `AST` of some query |
| 130 | +* `ydb.ScanQueryMode` - for fullscan `DQL` queries |
| 131 | +* `ydb.SchemeQueryMode` - for `DDL` queries |
| 132 | +* `ydb.ScriptingQueryMode` - for `DDL`, `DML`, `DQL` queries (not a `TCL`). Be careful: queries executes longer than with other query modes and consumes bigger server-side resources |
48 | 133 |
|
49 | | -## Query modes |
| 134 | +Example for changing default query mode: |
| 135 | +``` |
| 136 | +res, err = db.ExecContext(ydb.WithQueryMode(ctx, ydb.SchemeQueryMode), |
| 137 | + "DROP TABLE `/full/path/to/table/series`", |
| 138 | +) |
| 139 | +``` |
50 | 140 |
|
51 | | -## Specify `YDB` transaction control |
| 141 | +## Specify `YDB` transaction control <a name="tx-control"></a> |
52 | 142 |
|
53 | 143 | ## Retryer's for `YDB` `database/sql` driver |
54 | 144 |
|
|
0 commit comments