Skip to content

Commit 7b20c4d

Browse files
Maisem Alimaisem
authored andcommitted
sqlite: add ability to do ReadOnly tx using context annotations
Updates tailscale/corp#7265 Signed-off-by: Maisem Ali <maisem@tailscale.com>
1 parent 28d8b25 commit 7b20c4d

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

sqlite.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
// This driver requires a file: URI always be used to open a database.
88
// For details see https://sqlite.org/c3ref/open.html#urifilenames.
99
//
10-
//
11-
// Initializing connections or tracing
10+
// # Initializing connections or tracing
1211
//
1312
// If you want to do initial configuration of a connection, or enable
1413
// tracing, use the Connector function:
@@ -18,8 +17,7 @@
1817
// }
1918
// db, err = sql.OpenDB(sqlite.Connector(sqliteURI, connInitFunc, nil))
2019
//
21-
//
22-
// Memory Mode
20+
// # Memory Mode
2321
//
2422
// In-memory databases are popular for tests.
2523
// Use the "memdb" VFS (*not* the legacy in-memory modes) to be compatible
@@ -29,8 +27,7 @@
2927
//
3028
// Use a different dbname for each memory database opened.
3129
//
32-
//
33-
// Binding Types
30+
// # Binding Types
3431
//
3532
// SQLite is flexible about type conversions, and so is this driver.
3633
// Almost all "basic" Go types (int, float64, string) are accepted and
@@ -39,8 +36,7 @@
3936
// Values that implement encoding.TextMarshaler or json.Marshaler are
4037
// stored in SQLite in their marshaled form.
4138
//
42-
//
43-
// Binding Time
39+
// # Binding Time
4440
//
4541
// While SQLite3 has no strict time datatype, it does have a series of built-in
4642
// functions that operate on timestamps that expect columns to be in one of many
@@ -50,9 +46,9 @@
5046
// shortest timestamp format that can accurately represent the time.Time.
5147
// The supported formats are:
5248
//
53-
// 2. YYYY-MM-DD HH:MM
54-
// 3. YYYY-MM-DD HH:MM:SS
55-
// 4. YYYY-MM-DD HH:MM:SS.SSS
49+
// 2. YYYY-MM-DD HH:MM
50+
// 3. YYYY-MM-DD HH:MM:SS
51+
// 4. YYYY-MM-DD HH:MM:SS.SSS
5652
//
5753
// If the time.Time is not UTC (strongly consider storing times in UTC!),
5854
// we follow SQLite's norm of appending "[+-]HH:MM" to the above formats.
@@ -62,8 +58,7 @@
6258
// in the link above. If you want to do that, pass the result of time.Time.Unix
6359
// to the driver.
6460
//
65-
//
66-
// Reading Time
61+
// # Reading Time
6762
//
6863
// In general, time is hard to extract from SQLite as a time.Time.
6964
// If a column is defined as DATE or DATETIME, then text data is parsed
@@ -280,12 +275,24 @@ func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, e
280275
// Raw is so ConnInitFunc can cast to SQLConn.
281276
func (c *conn) Raw(fn func(interface{}) error) error { return fn(c) }
282277

278+
type readOnlyKey struct{}
279+
280+
// ReadOnly applies the query_only pragma to the connection.
281+
func ReadOnly(ctx context.Context) context.Context {
282+
return context.WithValue(ctx, readOnlyKey{}, true)
283+
}
284+
285+
// IsReadOnly reports whether the context has the ReadOnly key.
286+
func IsReadOnly(ctx context.Context) bool {
287+
return ctx.Value(readOnlyKey{}) != nil
288+
}
289+
283290
func (c *conn) txInit(ctx context.Context) error {
284291
if c.txState != txStateInit {
285292
return nil
286293
}
287294
c.txState = txStateBegun
288-
if c.readOnly {
295+
if c.readOnly || IsReadOnly(ctx) {
289296
if err := c.execInternal(ctx, "BEGIN"); err != nil {
290297
return err
291298
}

0 commit comments

Comments
 (0)