{"id":24638201,"url":"https://github.com/miyamo2/pqxd","last_synced_at":"2026-03-10T23:03:49.760Z","repository":{"id":259674987,"uuid":"829696963","full_name":"miyamo2/pqxd","owner":"miyamo2","description":"pqxd, the `database/sql` driver for PartiQL in Amazon DynamoDB","archived":false,"fork":false,"pushed_at":"2026-01-28T18:43:31.000Z","size":217,"stargazers_count":3,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-01T14:46:45.012Z","etag":null,"topics":["amazon-dynamodb","aws","aws-dynamodb","database-sql","dynamo","dynamodb","dynamodb-client","go","golang","partiql","pqxd","sql","sql-driver"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/miyamo2.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-07-16T23:24:35.000Z","updated_at":"2025-11-04T20:31:33.000Z","dependencies_parsed_at":"2024-10-27T09:16:55.032Z","dependency_job_id":"c4efb20a-9ac6-4f8f-9ad9-8da9576a9275","html_url":"https://github.com/miyamo2/pqxd","commit_stats":null,"previous_names":["miyamo2/pqxd"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/miyamo2/pqxd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miyamo2%2Fpqxd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miyamo2%2Fpqxd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miyamo2%2Fpqxd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miyamo2%2Fpqxd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/miyamo2","download_url":"https://codeload.github.com/miyamo2/pqxd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miyamo2%2Fpqxd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30360637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"ssl_error","status_checked_at":"2026-03-10T21:40:59.357Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["amazon-dynamodb","aws","aws-dynamodb","database-sql","dynamo","dynamodb","dynamodb-client","go","golang","partiql","pqxd","sql","sql-driver"],"created_at":"2025-01-25T10:13:26.231Z","updated_at":"2026-03-10T23:03:49.754Z","avatar_url":"https://github.com/miyamo2.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pqxd - [database/sql](https://golang.org/pkg/database/sql/)  driver for [PartiQL in DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/miyamo2/pqxd.svg)](https://pkg.go.dev/github.com/miyamo2/pqxd)\n[![CI](https://github.com/miyamo2/pqxd/actions/workflows/ci.yaml/badge.svg)](https://github.com/miyamo2/pqxd/actions/workflows/ci.yaml)\n[![GitHub go.mod Go version (subdirectory of monorepo)](https://img.shields.io/github/go-mod/go-version/miyamo2/pqxd?logo=go)](https://img.shields.io/github/go-mod/go-version/miyamo2/pqxd?logo=go)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/miyamo2/pqxd)](https://img.shields.io/github/v/release/miyamo2/pqxd)\n[![Go Report Card](https://goreportcard.com/badge/github.com/miyamo2/pqxd)](https://goreportcard.com/report/github.com/miyamo2/pqxd)\n[![GitHub License](https://img.shields.io/github/license/miyamo2/pqxd?\u0026color=blue)](https://img.shields.io/github/license/miyamo2/pqxd?\u0026color=blue)\n\n## Quick Start\n\n### Install\n\n```sh\ngo get github.com/miyamo2/pqxd\n```\n\n### Usage\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t\"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/miyamo2/pqxd\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tcfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(\"ap-northeast-1\"))\n\tif err != nil {\n\t\tlog.Fatalf(\"unable to load SDK config, %v\", err)\n\t}\n\tdb := sql.OpenDB(pqxd.NewConnector(cfg))\n\tif db == nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := db.Ping(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), time.Second)\n\tdefer cancel()\n\n\trows, err := db.QueryContext(ctx, `SELECT id, name FROM \"users\"`)\n\tif err != nil {\n\t\tfmt.Printf(\"something happend. err: %s\\n\", err.Error())\n\t\treturn\n\t}\n\n\tfor rows.NextResultSet() { // page feed with next token\n\t\tfor rows.Next() {\n\t\t\tvar (\n\t\t\t\tid   string\n\t\t\t\tname string\n\t\t\t)\n\t\t\tif err := rows.Scan(\u0026id, \u0026name); err != nil {\n\t\t\t\tfmt.Printf(\"something happend. err: %s\\n\", err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfmt.Printf(\"id: %s, name: %s\\n\", id, name)\n\t\t}\n\t}\n}\n```\n\n\u003e [!Important]\n\u003e If `Ping` is to be performed, `dynamodb:ListTables` policy must be set for the IAM role.\n\n#### `SELECT`\n\n\u003e [!TIP]\n\u003e If `*` is specified in the select column list,  \n\u003e the results of the rows are automatically sorted by column name(asc).\n\u003e \n\u003e However, if specified with *, the number of attributes may differ from row to row. \n\u003e \n\u003e Therefore, it is recommended that the selection column list specify the attribute names.\n\n##### Scan\n\n```go\nrows, err := db.QueryContext(context.Background(), `SELECT id, name FROM \"users\"`)\nfor rows.NextResultSet() { // page feed with next token\n    for rows.Next() {\n        var (\n            id string\n            name string\n        )\n        if err := rows.Scan(\u0026id, \u0026name); err != nil {\n            fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n            continue\n        }\n        fmt.Printf(\"id: %s, name: %s\\n\", id, name)\n    }\n}\n```\n\n##### GetItem\n\n```go\nrow := db.QueryRowContext(context.Background(), `SELECT id, name FROM \"users\" WHERE id = ?`, \"1\")\nvar (\n    id string\n    name string\n)\nif err := row.Scan(\u0026id, \u0026name); err != nil {\n    fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n    return\n}\nfmt.Printf(\"id: %s, name: %s\\n\", id, name)\n```\n\n##### GetItem with Global Secondary Index\n\n```go\nrow := db.QueryRowContext(context.Background(), `SELECT id, name FROM \"users\".\"gsi_pk-gsi-sk_index\" WHERE gsi_pk = ? AND gsi_sk = ?`, \"foo\", \"bar\")\n\nvar (\n    id string\n    name string\n)\nif err := row.Scan(\u0026id, \u0026name); err != nil {\n    fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n    return\n}\nfmt.Printf(\"id: %s, name: %s\\n\", id, name)\n```\n\n##### With Prepared Statement\n\n```go\nctx := context.Background()\n\nstmt, err := db.PrepareContext(ctx, `SELECT id, name FROM \"users\" WHERE id = ?`)\nif err != nil {\n    fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n    return\n}\ndefer stmt.Close()\n\nrows, err := stmt.QueryRowContext(ctx, \"1\")\nif err != nil {\n    fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n    return\n}\n\nvar (\n    id string\n    name string\n)\nif err := row.Scan(\u0026id, \u0026name); err != nil {\n    fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n    return\n}\nfmt.Printf(\"id: %s, name: %s\\n\", id, name)\n```\n\n##### With Transaction\n\n```go\ntx, err := db.Begin()\nif err != nil {\n    return err\n}\n\nctx := context.Background()\n\nrows, err := tx.QueryContext(ctx, `SELECT id, name FROM \"users\" WHERE id = ?`, \"1\")\nif err != nil {\n    tx.Rollback()\n    return err\n}\n\nrow := tx.QueryRowContext(ctx, `SELECT id, name FROM \"users\" WHERE id = ?`, \"2\")\n\n// WARNING: Do not use `tx.Commit()` when using `SELECT` statement.\n//\n// Each `sql.Rows` or `sql.Row` is resolved \n// the first time `rows.NextResultSet()`, `rows.Next()` or `row.Scan()` \n// is performed within that transaction.\n// So, after the `rows.NextResultSet()`, `rows.Next()` or `row.Scan()` is performed,\n// the transaction is automatically committed.\nfor rows.Next() {\n    var (\n        id string\n        name string\n    )\n    if err := rows.Scan(\u0026id, \u0026name); err != nil {\n        fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n        continue\n    }\n    fmt.Printf(\"id: %s, name: %s\\n\", id, name)\n}\n\nvar (\n    id string\n    name string\n)\nif err := row.Scan(\u0026id, \u0026name); err != nil {\n    fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n    return\n}\nfmt.Printf(\"id: %s, name: %s\\n\", id, name)\n```\n\n##### `RETURNING`\n\n`pqxd` supports the `RETURNING` clause.\n\n```go\nrow := db.QueryRowContext(context.Background(), `UPDATE \"users\" SET name = ? SET nickname = ? WHERE id = ? RETURNING MODIFIED OLD *`, \"David\", \"Dave\", \"3\")\n\nvar name, nickname sql.NullString\nvar disabled sql.NullBool\nif err := row.Scan(\u0026name, \u0026nickname); err != nil {\n    fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n    return\n}\nif name.Valid {\n    fmt.Printf(\"name: %s\\n\", name.String)\n}\nif nickname.Valid {\n    fmt.Printf(\"nickname: %s\\n\", nickname.String)\n}\n```\n\nAnd provides individual syntax for specifying a column list instead of `*`.\n\n```go\nrow := db.QueryRowContext(context.Background(), `UPDATE \"users\" SET name = ? SET nickname = ? WHERE id = ? RETURNING ALL OLD id`, \"Robert\", \"Bob\", \"2\")\n\nvar id string\nif err := row.Scan(\u0026id); err != nil {\n    fmt.Printf(\"something happend. err: %s\\n\", err.Error())\n    return\n}\nfmt.Printf(\"id: %s\\n\", id)\n```\n\n##### Describe Table\n\n`pqxd` supports the [DescribeTable API](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html) with `!pqxd_describe_table`, the meta-table.\n\n```go\nrow := db.QueryRowContext(context.Background(), `SELECT TableStatus FROM \"!pqxd_describe_table\" WHERE table_name = ?`, \"users\")\n\nvar tableStatus pqxd.TableStatus\nif err := row.Scan(\u0026tableStatus); err != nil {\n    fmt.Println(err.Error())\n    return\n}\nfmt.Printf(\"TableStatus: %v\\n\", tableStatus)\n```\n\n##### List Tables\n\n`pqxd` supports the [ListTables API](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ListTables.html) with `!pqxd_list_tables`, the meta-table.\n\n```go\nrows, err := db.QueryContext(context.Background(), `SELECT * FROM \"!pqxd_list_tables\"`)\n\nfor rows.NextResultSet() { // page feed with last-evaluated-key\n    for rows.Next() {\n        var tableName string\n        if err := rows.Scan(\u0026tableName); err != nil {\n            fmt.Println(err.Error())\n            continue\n        }\n        fmt.Printf(\"tableName: %s\\n\", tableName)\n    }\n}\n```\n\n#### `INSERT`/`UPDATE`/`DELETE`\n\n```go\ninsertResult, err := db.Exec(`INSERT INTO \"users\" VALUE { 'id': ?, 'name': ? }`, \"3\", \"Alice\")\nif err != nil {\n    return err\n}\naffected, err := insertResult.RowsAffected()\nif err != nil {\n    return err\n}\nif affected != 1 {\n    return fmt.Errorf(\"expected 1 row affected, got %d\", affected)\n}\n\nupdateResult, err := db.Exec(`UPDATE \"users\" SET name = ? WHERE id = ?`, \"Bob\", \"2\")\nif err != nil {\n    return err\n}\naffected, err = updateResult.RowsAffected()\nif err != nil {\n    return err\n}\nif affected != 1 {\n    return fmt.Errorf(\"expected 1 row affected, got %d\", affected)\n}\n\ndeleteResult, err := db.Exec(`DELETE FROM \"users\" WHERE id = ?`, \"1\")\nif err != nil {\n    return err\n}\naffected, err = deleteResult.RowsAffected()\nif err != nil {\n    return err\n}\nif affected != 1 {\n    return fmt.Errorf(\"expected 1 row affected, got %d\", affected)\n}\n```\n\n##### With Prepared Statement\n\n```go\nstmt, err := db.Prepare(`INSERT INTO \"users\" VALUE { 'id': ?, 'name': ? }`)\nif err != nil {\n    return err\n}\ndefer stmt.Close()\n\ninsertResult, err := stmt.Exec(\"3\", \"Alice\")\nif err != nil {\n    return err\n}\naffected, err := insertResult.RowsAffected()\nif err != nil {\n    return err\n}\nif affected != 1 {\n    return fmt.Errorf(\"expected 1 row affected, got %d\", affected)\n}\n```\n\n##### With Transaction\n\n```go\ntx, err := db.Begin()\nif err != nil {\n    return err\n}\n\ninsertResult, err := tx.Exec(`INSERT INTO \"users\" VALUE { 'id': ?, 'name': ? }`, \"3\", \"Alice\")\nif err != nil {\n    tx.Rollback()\n    return err\n}\n\nupdateResult, err := tx.Exec(`UPDATE \"users\" SET name = ? WHERE id = ?`, \"Bob\", \"2\")\nif err != nil {\n    tx.Rollback()\n    return err\n}\n\ndeleteResult, err := tx.Exec(`DELETE FROM \"users\" WHERE id = ?`, \"1\")\nif err != nil {\n    tx.Rollback()\n    return err\n}\n\n// RowsAffected is available after commit\ntx.Commit()\n\n// RowsAffected might return 0 or 1. If 0, it means statement is not successful.\nif affected, err := insertResult.RowsAffected(); err != nil || affected != 1 {\n    return err\n}\n\nif affected, err := updateResult.RowsAffected(); err != nil || affected != 1 {\n    return err\n}\n\nif affected, err := deleteResult.RowsAffected(); err != nil || affected != 1 {\n    return err\n}\n```\n\n#### DSN(Data Source Name) String\n\nWe recommend using `sql.OpenDB` with `pqxd.NewConnector` instead of `sql.Open`.\nBut if you want to use `sql.Open`, you can use the following DSN string.\n\n```sh\nAWS_REGION=\u003caws region\u003e\n;AWS_ACCESS_KEY_ID=\u003caccess key ID\u003e\n;AWS_SECRET_ACCESS_KEY=\u003csecret access key\u003e\n[;ENDPOINT=\u003camazon dynamodb endpoint\u003e]\n```\n\n| Key                     | description                                                                                                                                                                                                                                      |\n|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `AWS_REGION`            | [AWS Region](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-regions). If not supplied, it is resolved from one of the following environment variables; `AWS_REGION` or `AWS_DEFAULT_REGION`. |\n| `AWS_ACCESS_KEY_ID`     | [AWS Access Key ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html). If not supplied, it is resolved from one of the following environment variables; `AWS_ACCESS_KEY` or `AWS_ACCESS_KEY_ID`.                 |\n| `AWS_SECRET_ACCESS_KEY` | [AWS Secret Access Key](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html). If not supplied, it is resolved from one of the following environment variables; `AWS_SECRET_KEY` or `AWS_SECRET_ACCESS_KEY`.         |\n| `ENDPOINT`              | Endpoint of DynamoDB. Used to connect locally to an emulator or to a DynamoDB compatible interface.                                                                                                                                              |\n\n```go\ndb, err := sql.Open(pqxd.DriverName, \"AWS_REGION=ap-northeast-1;AWS_ACCESS_KEY_ID=AKIA...;AWS_SECRET_ACCESS_KEY=...;\")\n```\n\n\u003e [!TIP]\n\u003e If the application is run on AWS Lambda, connections can be obtained even if the DSN is an empty string.\n\u003e This is because the region, access key, and secret key are defined as [runtime environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime).\n\n#### O11y\n\n##### New Relic\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"log\"\n\n\t\"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/miyamo2/pqxd\"\n\tnraws \"github.com/newrelic/go-agent/v3/integrations/nrawssdk-v2\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tcfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(\"ap-northeast-1\"))\n\tif err != nil {\n\t\tlog.Fatalf(\"unable to load SDK config, %v\", err)\n\t}\n\n\t// Instrumenting New Relic\n\tnraws.AppendMiddlewares(\u0026cfg.APIOptions, nil)\n\n\tdb := sql.OpenDB(pqxd.NewConnector(cfg))\n\tif db == nil {\n\t\tlog.Fatal(err)\n\t}\n\tdb.Ping()\n}\n```\n\n##### Datadog\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"log\"\n\n\t\"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/miyamo2/pqxd\"\n\tawstrace \"gopkg.in/DataDog/dd-trace-go.v1/contrib/aws/aws-sdk-go-v2/aws\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tcfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(\"ap-northeast-1\"))\n\tif err != nil {\n\t\tlog.Fatalf(\"unable to load SDK config, %v\", err)\n\t}\n\n\t// Instrumenting Datadog\n\tawstrace.AppendMiddleware(\u0026cfg)\n\n\tdb := sql.OpenDB(pqxd.NewConnector(cfg))\n\tif db == nil {\n\t\tlog.Fatal(err)\n\t}\n\tdb.Ping()\n}\n```\n\n##### AWS X-Ray\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"log\"\n\n\t\"github.com/miyamo2/pqxd\"\n\n\t\"github.com/aws/aws-sdk-go-v2/aws\"\n\t\"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/aws/aws-sdk-go-v2/service/dynamodb\"\n\t\"github.com/aws/aws-xray-sdk-go/instrumentation/awsv2\"\n\t\"github.com/aws/aws-xray-sdk-go/xray\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tcfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(\"ap-northeast-1\"))\n\tif err != nil {\n\t\tlog.Fatalf(\"unable to load SDK config, %v\", err)\n\t}\n\t\n\t// Instrumenting X-Ray\n\tawsv2.AWSV2Instrumentor(\u0026cfg.APIOptions)\n\n\tdb := sql.OpenDB(pqxd.NewConnector(cfg))\n\tif db == nil {\n\t\tlog.Fatal(err)\n\t}\n\tdb.Ping()\n}\n```\n\n## Contributing\n\nFeel free to open a PR or an Issue.\n\nHowever, you must promise to follow our [Code of Conduct](https://github.com/miyamo2/pqxd/blob/main/CODE_OF_CONDUCT.md).\n\n### Tasks\n\nWe recommend that this section be run with [xc](https://github.com/joerdav/xc)\n\n#### test:unit\n\n```sh\ngo test -v -coverpkg='github.com/miyamo2/pqxd' -coverprofile=coverage.out\n```\n\n#### test:integration\n\n```sh\ncd tests/integration\nxc test\n```\n\n## License\n\n**pqxd** released under the [MIT License](https://github.com/miyamo2/pqxd/blob/main/LICENSE)\n\n## Special Thanks\n\n`pqxd` is inspired by the following projects.  \nWith the utmost respect, we would like to thank the authors and contributors of these projects.\n\n- [btnguyen2k/godynamo](https://github.com/btnguyen2k/godynamo)\n- [go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)\n- [lib/pq](https://github.com/lib/pq)\n- [jackc/pgx](https://github.com/jackc/pgx)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiyamo2%2Fpqxd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmiyamo2%2Fpqxd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiyamo2%2Fpqxd/lists"}