{"id":42482623,"url":"https://github.com/cloudspannerecosystem/spanner-truncate","last_synced_at":"2026-01-28T11:15:46.773Z","repository":{"id":36989821,"uuid":"315594773","full_name":"cloudspannerecosystem/spanner-truncate","owner":"cloudspannerecosystem","description":"spanner-truncate is a tool to delete all rows from the tables in a Cloud Spanner database without deleting tables themselves.","archived":false,"fork":false,"pushed_at":"2024-06-07T01:53:38.000Z","size":75,"stargazers_count":27,"open_issues_count":2,"forks_count":9,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-06-20T05:05:49.834Z","etag":null,"topics":[],"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/cloudspannerecosystem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2020-11-24T10:20:45.000Z","updated_at":"2024-02-08T09:00:29.000Z","dependencies_parsed_at":"2024-02-13T14:25:20.202Z","dependency_job_id":"15687e79-a8e4-48c1-bf14-1f8f97147f03","html_url":"https://github.com/cloudspannerecosystem/spanner-truncate","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/cloudspannerecosystem/spanner-truncate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudspannerecosystem%2Fspanner-truncate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudspannerecosystem%2Fspanner-truncate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudspannerecosystem%2Fspanner-truncate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudspannerecosystem%2Fspanner-truncate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudspannerecosystem","download_url":"https://codeload.github.com/cloudspannerecosystem/spanner-truncate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudspannerecosystem%2Fspanner-truncate/sbom","scorecard":{"id":293297,"data":{"date":"2025-08-11","repo":{"name":"github.com/cloudspannerecosystem/spanner-truncate","commit":"3ee90eac17bdaacb20e5abf052e1bcebd8ce4188"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.1,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":7,"reason":"Found 8/11 approved changesets -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/run-tests.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run-tests.yaml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/cloudspannerecosystem/spanner-truncate/run-tests.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run-tests.yaml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/cloudspannerecosystem/spanner-truncate/run-tests.yaml/main?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T18:51:43.985Z","repository_id":36989821,"created_at":"2025-08-17T18:51:43.986Z","updated_at":"2025-08-17T18:51:43.986Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28844862,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T10:53:21.605Z","status":"ssl_error","status_checked_at":"2026-01-28T10:53:20.789Z","response_time":57,"last_error":"SSL_read: 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":[],"created_at":"2026-01-28T11:15:46.126Z","updated_at":"2026-01-28T11:15:46.768Z","avatar_url":"https://github.com/cloudspannerecosystem.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"spanner-truncate\n===\n[![run-tests](https://github.com/cloudspannerecosystem/spanner-truncate/actions/workflows/run-tests.yaml/badge.svg)](https://github.com/cloudspannerecosystem/spanner-truncate/actions/workflows/run-tests.yaml)\n\n## Overview\n\nspanner-truncate is a tool to delete all rows from the tables in a Cloud Spanner database without deleting tables themselves.\n\nPlease feel free to report issues and send pull requests, but note that this application is not officially supported as part of the Cloud Spanner product.\n\n## Use cases\n\n* Delete rows from the database while keeping the underlying splits, which are typically for [database pre-warming before the launch](https://cloud.google.com/solutions/best-practices-cloud-spanner-gaming-database#pre-warm_the_database_before_launch).\n* Delete rows from the database without requiring strong IAM permissions for deleting tables or databases.\n\n## Motivation\n\nAt a glance deleting all rows from the database looks an easy task, but there are several issues we could encounter when we want to delete rows from the real-world databases.\n\n* If the table size is huge, a simple DELETE statement like `DELETE FROM table WHERE true` could easily exceed the [transaction mutation limit](https://cloud.google.com/spanner/quotas).\n* Rows in interleaved tables which have `PARENT ON DELETE NO ACTION` must be deleted first before deleting the rows from the parent table, otherwise it will cause a constraint violation error.\n* Rows in the tables which reference other tables with `FOREIGN KEY` constraints must be deleted first before deleting rows in the referenced tables, otherwise it will cause a constraint violation error.\n* It would take a lot of time if we delete rows from the tables one by one.\n\n## How this tool works\n\nTo solve the preceding issues, this tool works as follows.\n\n* Use [Partitioned DML](https://cloud.google.com/spanner/docs/dml-partitioned) to delete all rows from the table to overcome the single transaction mutation limit.\n* Delete rows from multiple tables in parallel to minimize the total time for deletion.\n* Automatically discover the constraints between tables and delete rows from the tables in proper order without violating database constraints.\n\n## Limitations\n\n* This tool does not guarantee the atomicity of deletion. If you access the rows that are being deleted, you will get the inconsistent view of the database.\n* This tool does not delete rows which were inserted while the tool was running.\n* This tool does not support truncating tables that use foreign key constraints in some scenarios:\n  * If there is a circular dependency among the tables, truncation will be failed.\n  * If --tables is used for a table that is referenced by other tables with ON DELETE CASCADE, such tables will also be truncated.\n  * If `--exclude-tables` is used only for the referencing table that has ON DELETE CASCADE, that table will be truncated by cascade-deletion of the referenced table.\n\n## Install\n\n```\nGO111MODULE=on go get github.com/cloudspannerecosystem/spanner-truncate\n```\n\n## How to use\n\n```\nUsage:\n  spanner-truncate [OPTIONS]\n\nApplication Options:\n  -p, --project=  (required) GCP Project ID. [$SPANNER_PROJECT_ID]\n  -i, --instance= (required) Cloud Spanner Instance ID. [$SPANNER_INSTANCE_ID]\n  -d, --database= (required) Cloud Spanner Database ID. [$SPANNER_DATABASE_ID]\n  -q, --quiet     Disable all interactive prompts.\n  -t, --tables=   Comma separated table names to be truncated. Default to truncate all tables if not specified. If an interleaved table is specified, its descendants tables are also truncated.\n  -e, --exclude-tables Comma separated table names to be exempted from truncating. 'tables' and 'exclude-tables' cannot co-exist. If an interleaved table is specified, its ancestors tables are also excluded.\nHelp Options:\n  -h, --help      Show this help message\n```\n\nExample:\n\n```\n$ spanner-truncate -p myproject -i myinstance -d mydb\nFetching table information from projects/myproject/instances/myinstance/databases/mydb\nAlbums\nConcerts\nSingers\nSongs\n\nRows in these tables will be deleted. Do you want to continue? [Y/n] Y\nConcerts: completed    13s [============================================\u003e] 100% (1,200 / 1,200)\nSingers:  completed    13s [============================================\u003e] 100% (6,000 / 6,000)\nAlbums:   completed    12s [============================================\u003e] 100% (1,800 / 1,800)\nSongs:    completed    11s [============================================\u003e] 100% (3,600 / 3,600)\n\nDone! All rows have been deleted successfully.\n```\n\n## Import as a Go package\n\nYou can also use spanner-truncate as a Go library from your Go application. The entry point is [Run](https://pkg.go.dev/github.com/cloudspannerecosystem/spanner-truncate/truncate#Run) function in `truncate` package. If you have some subsequent processes using a client, you can use [RunWithClient](https://pkg.go.dev/github.com/cloudspannerecosystem/spanner-truncate/truncate#RunWithClient). You can pass the externally generated client to the function and avoids the use of redundant clients.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudspannerecosystem%2Fspanner-truncate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudspannerecosystem%2Fspanner-truncate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudspannerecosystem%2Fspanner-truncate/lists"}