Skip to content

Commit 79d6aad

Browse files
committed
fix tests + supports primitive go's value types as sql.Named() + databasq/sql docs
1 parent fd46135 commit 79d6aad

File tree

9 files changed

+498
-50
lines changed

9 files changed

+498
-50
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
* Changed output of `sugar.GenerateDeclareSection` (added error as second result)
22
* Specified `sugar.GenerateDeclareSection` for `go1.18` (supports input types `*table.QueryParameters` `[]table.ParameterOption` or `[]sql.NamedArg`)
3-
* Added `database/sql` example and docs (WIP)
3+
* Supports different go's primitive value types as arg of `sql.Named("name", value)`
4+
* Added `database/sql` example and docs
45

56
## v3.36.1
67
* Fixed `xsql.Rows` error checking

SQL.md

Lines changed: 129 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,144 @@
11
# `database/sql` driver for `YDB`
22

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.
45

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
927
)
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
2630
}
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
3233
)
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)
36110
}
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.
42122

43-
## Execute queries
123+
Thats why needs to select query mode on client side currently.
44124

45-
### On database object
125+
`YDB` team have a roadmap goal to implements a single method for executing different query types.
46126

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
48133

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+
```
50140

51-
## Specify `YDB` transaction control
141+
## Specify `YDB` transaction control <a name="tx-control"></a>
52142

53143
## Retryer's for `YDB` `database/sql` driver
54144

internal/repeater/repeater_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func TestRepeaterForceLogBackoff(t *testing.T) {
8383
}
8484
lastWakeUp = fakeClock.Now()
8585
wakeUps++
86-
return fmt.Errorf("spatial error for force with log backoff")
86+
return fmt.Errorf("special error for force with log backoff")
8787
}, WithClock(fakeClock))
8888
defer r.Stop()
8989

internal/xsql/convert.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,34 +48,68 @@ func primitiveToValue(v interface{}) (value types.Value, err error) {
4848
return x, nil
4949
case bool:
5050
return types.BoolValue(x), nil
51+
case *bool:
52+
return types.NullableBoolValue(x), nil
5153
case int8:
5254
return types.Int8Value(x), nil
55+
case *int8:
56+
return types.NullableInt8Value(x), nil
5357
case uint8:
5458
return types.Uint8Value(x), nil
59+
case *uint8:
60+
return types.NullableUint8Value(x), nil
5561
case int16:
5662
return types.Int16Value(x), nil
63+
case *int16:
64+
return types.NullableInt16Value(x), nil
5765
case uint16:
5866
return types.Uint16Value(x), nil
67+
case *uint16:
68+
return types.NullableUint16Value(x), nil
5969
case int32:
6070
return types.Int32Value(x), nil
71+
case *int32:
72+
return types.NullableInt32Value(x), nil
6173
case uint32:
6274
return types.Uint32Value(x), nil
75+
case *uint32:
76+
return types.NullableUint32Value(x), nil
6377
case int64:
6478
return types.Int64Value(x), nil
79+
case *int64:
80+
return types.NullableInt64Value(x), nil
6581
case uint64:
6682
return types.Uint64Value(x), nil
83+
case *uint64:
84+
return types.NullableUint64Value(x), nil
6785
case float32:
6886
return types.FloatValue(x), nil
87+
case *float32:
88+
return types.NullableFloatValue(x), nil
6989
case float64:
7090
return types.DoubleValue(x), nil
91+
case *float64:
92+
return types.NullableDoubleValue(x), nil
7193
case []byte:
72-
return types.StringValue(x), nil
94+
return types.BytesValue(x), nil
95+
case *[]byte:
96+
return types.NullableBytesValue(x), nil
7397
case string:
74-
return types.UTF8Value(x), nil
98+
return types.TextValue(x), nil
99+
case *string:
100+
return types.NullableTextValue(x), nil
75101
case [16]byte:
76102
return types.UUIDValue(x), nil
103+
case *[16]byte:
104+
return types.NullableUUIDValue(x), nil
77105
case time.Time:
78-
return types.DateValueFromTime(x), nil
106+
return types.TimestampValueFromTime(x), nil
107+
case *time.Time:
108+
return types.NullableTimestampValueFromTime(x), nil
109+
case time.Duration:
110+
return types.IntervalValueFromDuration(x), nil
111+
case *time.Duration:
112+
return types.NullableIntervalValueFromDuration(x), nil
79113
default:
80114
return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: unsupported type: %T", x))
81115
}

sugar/params_go1.18.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//go:build go1.18
2-
// +build go1.18
3-
41
package sugar
52

63
import (

0 commit comments

Comments
 (0)