{"id":18533114,"url":"https://github.com/googleapis/go-sql-spanner","last_synced_at":"2025-05-15T20:07:30.461Z","repository":{"id":40001484,"uuid":"331464514","full_name":"googleapis/go-sql-spanner","owner":"googleapis","description":"Google Cloud Spanner driver for Go's database/sql package.","archived":false,"fork":false,"pushed_at":"2025-05-13T09:04:05.000Z","size":1356,"stargazers_count":110,"open_issues_count":4,"forks_count":24,"subscribers_count":45,"default_branch":"main","last_synced_at":"2025-05-13T09:26:27.824Z","etag":null,"topics":["database","golang","spanner"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/googleapis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-01-20T23:56:28.000Z","updated_at":"2025-05-13T09:04:08.000Z","dependencies_parsed_at":"2023-09-28T18:13:49.920Z","dependency_job_id":"1ec6fbce-fb83-41c8-8903-34fd80b05112","html_url":"https://github.com/googleapis/go-sql-spanner","commit_stats":{"total_commits":168,"total_committers":19,"mean_commits":8.842105263157896,"dds":0.7440476190476191,"last_synced_commit":"b721f1f043c47ce397b07b3bc0808f89679f8576"},"previous_names":["cloudspannerecosystem/go-sql-spanner"],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googleapis%2Fgo-sql-spanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googleapis%2Fgo-sql-spanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googleapis%2Fgo-sql-spanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googleapis%2Fgo-sql-spanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/googleapis","download_url":"https://codeload.github.com/googleapis/go-sql-spanner/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414499,"owners_count":22067272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","golang","spanner"],"created_at":"2024-11-06T19:09:26.066Z","updated_at":"2025-05-15T20:07:25.392Z","avatar_url":"https://github.com/googleapis.png","language":"Go","readme":"# go-sql-spanner\n\n[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go\u0026logoColor=white\u0026style=flat-square)](https://pkg.go.dev/github.com/googleapis/go-sql-spanner)\n\n[Google Cloud Spanner](https://cloud.google.com/spanner) driver for\nGo's [database/sql](https://golang.org/pkg/database/sql/) package.\n\n```go\nimport _ \"github.com/googleapis/go-sql-spanner\"\n\ndb, err := sql.Open(\"spanner\", \"projects/PROJECT/instances/INSTANCE/databases/DATABASE\")\nif err != nil {\n    log.Fatal(err)\n}\n\n// Print tweets with more than 500 likes.\nrows, err := db.QueryContext(ctx, \"SELECT id, text FROM tweets WHERE likes \u003e @likes\", sql.Named(\"likes\", 500))\nif err != nil {\n    log.Fatal(err)\n}\ndefer rows.Close()\n\nvar (\n    id   int64\n    text string\n)\nfor rows.Next() {\n    if err := rows.Scan(\u0026id, \u0026text); err != nil {\n        log.Fatal(err)\n    }\n    fmt.Println(id, text)\n}\n```\n\n## Statements\n\nStatements support follows the official [Google Cloud Spanner Go](https://pkg.go.dev/cloud.google.com/go/spanner) client\nstyle arguments as well as positional parameters. It is highly recommended to use either positional parameters in\ncombination with positional arguments, __or__ named parameters in combination with named arguments.\n\n### Using positional parameters with positional arguments\n\n```go\ndb.QueryContext(ctx, \"SELECT id, text FROM tweets WHERE likes \u003e ?\", 500)\n\ndb.ExecContext(ctx, \"INSERT INTO tweets (id, text, rts) VALUES (?, ?, ?)\", id, text, 10000)\n```\n\n### Using named parameters with named arguments\n\n```go\ndb.ExecContext(ctx, \"DELETE FROM tweets WHERE id = @id\", sql.Named(\"id\", 14544498215374))\n\ndb.ExecContext(ctx, \"INSERT INTO tweets (id, text, rts) VALUES (@id, @text, @rts)\",\n\tsql.Named(\"id\", id), sql.Named(\"text\", text), sql.Named(\"rts\", 10000))\n```\n\n### Using named parameters with positional arguments (not recommended)\nNamed parameters can also be used in combination with positional arguments,\nbut this is __not recommended__, as the behavior can be hard to predict if\nthe same named query parameter is used in multiple places in the statement.\n\n```go\n// Possible, but not recommended.\ndb.ExecContext(ctx, \"DELETE FROM tweets WHERE id = @id\", 14544498215374)\n```\n\n### Query Options\nQuery options can be passed in as arguments to a query. Pass in a value of\ntype `spannerdriver.ExecOptions` to supply additional execution options for\na statement. The `spanner.QueryOptions` will be passed through to the Spanner\nclient as the query options to use for the query or DML statement.\n\n```go\ntx.ExecContext(ctx, \"INSERT INTO Singers (SingerId, Name) VALUES (@id, @name)\",\n\tspannerdriver.ExecOptions{QueryOptions: spanner.QueryOptions{RequestTag: \"insert_singer\"}},\n    123, \"Bruce Allison\")\ntx.QueryContext(ctx, \"SELECT SingerId, Name FROM Singers WHERE SingerId = ?\",\n    spannerdriver.ExecOptions{QueryOptions: spanner.QueryOptions{RequestTag: \"select_singer\"}},\n    123)\n```\n\nStatement tags (request tags) can also be set using the custom SQL statement\n`set statement_tag='my_tag'`:\n\n```go\ntx.ExecContext(ctx, \"set statement_tag = 'select_singer'\")\ntx.QueryContext(ctx, \"SELECT SingerId, Name FROM Singers WHERE SingerId = ?\", 123)\n```\n\n## Transactions\n\n- Read-write transactions always uses the strongest isolation level and ignore the user-specified level.\n- Read-only transactions do strong-reads by default. Read-only transactions must be ended by calling\n  either Commit or Rollback. Calling either of these methods will end the current read-only\n  transaction and return the session that is used to the session pool.\n\n```go\ntx, err := db.BeginTx(ctx, \u0026sql.TxOptions{}) // Read-write transaction.\n\n// Read-write transaction with a transaction tag.\nconn, _ := db.Conn(ctx)\n_, _ := conn.ExecContext(ctx, \"SET TRANSACTION_TAG='my_transaction_tag'\")\ntx, err := conn.BeginTx(ctx, \u0026sql.TxOptions{})\n\n\ntx, err := db.BeginTx(ctx, \u0026sql.TxOptions{\n    ReadOnly: true, // Read-only transaction using strong reads.\n})\n\nconn, _ := db.Conn(ctx)\n_, _ := conn.ExecContext(ctx, \"SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'\")\ntx, err := conn.BeginTx(ctx, \u0026sql.TxOptions{\n    ReadOnly: true, // Read-only transaction using a 10 second exact staleness.\n})\n```\n\n## Transaction Runner (Retry Transactions)\n\nSpanner can abort a read/write transaction if concurrent modifications are detected\nthat would violate the transaction consistency. When this happens, the driver will\nreturn the `ErrAbortedDueToConcurrentModification` error. You can use the\n`RunTransaction` and `RunTransactionWithOptions` functions to let the driver\nautomatically retry transactions that are aborted by Spanner.\n\n```go\npackage sample\n\nimport (\n  \"context\"\n  \"database/sql\"\n  \"fmt\"\n\n  _ \"github.com/googleapis/go-sql-spanner\"\n  spannerdriver \"github.com/googleapis/go-sql-spanner\"\n)\n\nspannerdriver.RunTransactionWithOptions(ctx, db, \u0026sql.TxOptions{}, func(ctx context.Context, tx *sql.Tx) error {\n    row := tx.QueryRowContext(ctx, \"select Name from Singers where SingerId=@id\", 123)\n    var name string\n    if err := row.Scan(\u0026name); err != nil {\n        return err\n    }\n    return nil\n}, spanner.TransactionOptions{TransactionTag: \"my_transaction_tag\"})\n```\n\nSee also the [transaction runner sample](./examples/run-transaction/main.go).\n\n## DDL Statements\n\n[DDL statements](https://cloud.google.com/spanner/docs/data-definition-language)\nare not supported in transactions per Cloud Spanner restriction.\nInstead, run them on a connection without an active transaction:\n\n```go\ndb.ExecContext(ctx, \"CREATE TABLE ...\")\n```\n\nMultiple DDL statements can be sent in one batch to Cloud Spanner by defining a DDL batch:\n\n```go\nconn, _ := db.Conn(ctx)\n_, _ := conn.ExecContext(ctx, \"START BATCH DDL\")\n_, _ = conn.ExecContext(ctx, \"CREATE TABLE Singers (SingerId INT64, Name STRING(MAX)) PRIMARY KEY (SingerId)\")\n_, _ = conn.ExecContext(ctx, \"CREATE INDEX Idx_Singers_Name ON Singers (Name)\")\n// Executing `RUN BATCH` will run the previous DDL statements as one batch.\n_, _ := conn.ExecContext(ctx, \"RUN BATCH\")\n```\n\nSee also [the batch DDL example](/examples/ddl-batches).\n\n## Examples\n\nThe [`examples`](/examples) directory contains standalone code samples that show how to use common\nfeatures of Cloud Spanner and/or the database/sql package. Each standalone code sample can be\nexecuted without any prior setup, as long as Docker is installed on your local system.\n\n## Raw Connection / Specific Cloud Spanner Features\n\nUse the `Conn.Raw` method to get access to a Cloud Spanner specific connection instance. This\ninstance can be used to access Cloud Spanner specific features and settings, such as mutations,\nread-only staleness settings and commit timestamps.\n\n```go\nconn, _ := db.Conn(ctx)\n_ = conn.Raw(func(driverConn interface{}) error {\n    spannerConn, ok := driverConn.(spannerdriver.SpannerConn)\n    if !ok {\n        return fmt.Errorf(\"unexpected driver connection %v, expected SpannerConn\", driverConn)\n    }\n    // Use the `SpannerConn` interface to set specific Cloud Spanner settings or access\n    // specific Cloud Spanner features.\n\n    // Example: Set and get the current read-only staleness of the connection.\n    _ = spannerConn.SetReadOnlyStaleness(spanner.ExactStaleness(10 * time.Second))\n    _ = spannerConn.ReadOnlyStaleness()\n\n    return nil\n})\n```\n\nSee also the [examples](/examples) directory for further code samples.\n\n## Emulator\n\nSee [Google Cloud Spanner Emulator](https://cloud.google.com/spanner/docs/emulator) to learn how to start the emulator.\nOnce the emulator is started and the host environmental flag is set, the driver will automatically connect to the\nemulator.\n\n```\n$ gcloud beta emulators spanner start\n$ export SPANNER_EMULATOR_HOST=localhost:9010\n```\n\n## Spanner PostgreSQL Interface\n\nThis driver only works with the Spanner GoogleSQL dialect. For the\nSpanner PostgreSQL dialect, any PostgreSQL driver that implements the\n[database/sql](https://golang.org/pkg/database/sql/) interface can be used\nin combination with\n[PGAdapter](https://cloud.google.com/spanner/docs/pgadapter).\n\nFor example, the [pgx](https://github.com/jackc/pgx) driver can be used in combination with\nPGAdapter: https://github.com/GoogleCloudPlatform/pgadapter/blob/postgresql-dialect/docs/pgx.md\n\n## Troubleshooting\n\nThe driver will retry any Aborted error that is returned by Cloud Spanner\nduring a read/write transaction. If the driver detects that the data that\nwas used by the transaction was changed by another transaction between the\ninitial attempt and the retry attempt, the Aborted error will be propagated\nto the client application as an `spannerdriver.ErrAbortedDueToConcurrentModification`\nerror.\n\n## Go Versions Supported\n\nThe Spanner database/sql driver follows the [Go release policy](https://go.dev/doc/devel/release)\nand supports the two latest major Go versions.\n\n## Authorization\n\nBy default, each API will use [Google Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials)\nfor authorization credentials used in calling the API endpoints. This will allow your\napplication to run in many environments without requiring explicit configuration.\n\n## Contributing\n\nContributions are welcome. Please, see the\n[CONTRIBUTING](https://github.com/googleapis/go-sql-spanner/blob/main/CONTRIBUTING.md)\ndocument for details.\n\nPlease note that this project is released with a Contributor Code of Conduct.\nBy participating in this project you agree to abide by its terms.\nSee [Contributor Code of Conduct](https://github.com/googleapis/go-sql-spanner/blob/main/CODE_OF_CONDUCT.md)\nfor more information.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogleapis%2Fgo-sql-spanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoogleapis%2Fgo-sql-spanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogleapis%2Fgo-sql-spanner/lists"}