{"id":13709846,"url":"https://github.com/suketa/ruby-duckdb","last_synced_at":"2025-08-26T20:51:28.706Z","repository":{"id":35742727,"uuid":"218025521","full_name":"suketa/ruby-duckdb","owner":"suketa","description":"Ruby binding for DuckDB","archived":false,"fork":false,"pushed_at":"2025-08-07T21:04:04.000Z","size":3302,"stargazers_count":215,"open_issues_count":23,"forks_count":29,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-08-07T23:15:40.789Z","etag":null,"topics":["database","hacktoberfest","ruby"],"latest_commit_sha":null,"homepage":"https://github.com/suketa/ruby-duckdb","language":"Ruby","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/suketa.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","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,"zenodo":null},"funding":{"github":"suketa"}},"created_at":"2019-10-28T10:53:24.000Z","updated_at":"2025-08-07T21:03:14.000Z","dependencies_parsed_at":"2023-01-16T04:52:03.188Z","dependency_job_id":"7f8ef496-e9d4-4490-9ce5-c72241ce0cc5","html_url":"https://github.com/suketa/ruby-duckdb","commit_stats":{"total_commits":471,"total_committers":13,"mean_commits":36.23076923076923,"dds":0.08917197452229297,"last_synced_commit":"2174bae26bd61b4b8f3f788f22ca4f16f05db8e5"},"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"purl":"pkg:github/suketa/ruby-duckdb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suketa%2Fruby-duckdb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suketa%2Fruby-duckdb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suketa%2Fruby-duckdb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suketa%2Fruby-duckdb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/suketa","download_url":"https://codeload.github.com/suketa/ruby-duckdb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suketa%2Fruby-duckdb/sbom","scorecard":{"id":857938,"data":{"date":"2025-08-11","repo":{"name":"github.com/suketa/ruby-duckdb","commit":"114efc63000894859234d149eff28d6e70b142c8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.8,"checks":[{"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":"Maintained","score":10,"reason":"30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":1,"reason":"Found 2/13 approved changesets -- score normalized to 1","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":"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":"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":"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/make_documents.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/make_documents.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/make_documents.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/make_documents.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/make_documents.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/make_documents.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_on_macos.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/test_on_macos.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test_on_macos.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/test_on_macos.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_on_macos.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/test_on_macos.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_on_ubuntu.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/test_on_ubuntu.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test_on_ubuntu.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/test_on_ubuntu.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_on_ubuntu.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/test_on_ubuntu.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_on_windows.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/test_on_windows.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test_on_windows.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/suketa/ruby-duckdb/test_on_windows.yml/main?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:2","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   5 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage 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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/make_documents.yml:1","Warn: no topLevel permission defined: .github/workflows/test_on_macos.yml:1","Warn: no topLevel permission defined: .github/workflows/test_on_ubuntu.yml:1","Warn: no topLevel permission defined: .github/workflows/test_on_windows.yml: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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: 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":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-353f-x4gh-cqq8"],"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-24T00:24:52.166Z","repository_id":35742727,"created_at":"2025-08-24T00:24:52.166Z","updated_at":"2025-08-24T00:24:52.166Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272254471,"owners_count":24901048,"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","status":"online","status_checked_at":"2025-08-26T02:00:07.904Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["database","hacktoberfest","ruby"],"created_at":"2024-08-02T23:00:47.064Z","updated_at":"2025-08-26T20:51:28.698Z","avatar_url":"https://github.com/suketa.png","language":"Ruby","funding_links":["https://github.com/sponsors/suketa"],"categories":["Client APIs","Ruby"],"sub_categories":[],"readme":"# ruby-duckdb\n\n[![Ubuntu](https://github.com/suketa/ruby-duckdb/workflows/Ubuntu/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AUbuntu)\n[![MacOS](https://github.com/suketa/ruby-duckdb/workflows/MacOS/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AMacOS)\n[![Windows](https://github.com/suketa/ruby-duckdb/workflows/Windows/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AWindows)\n[![Gem Version](https://badge.fury.io/rb/duckdb.svg)](https://badge.fury.io/rb/duckdb)\n\n## Description\n\nThis gem `duckdb` is Ruby client for the [DuckDB](https://www.duckdb.org) database engine.\n\n## Requirement\n\nYou must have [DuckDB](https://www.duckdb.org) engine installed in order to use this gem.\n\n## Pre-requisite setup (Linux):\n1. Head over to the [DuckDB](https://duckdb.org/) webpage.\n\n2. Download the latest C++ package release for DuckDB.\n\n3. Move the files to their respective location:\n    - Extract the `duckdb.h` and `duckdb.hpp` file to `/usr/local/include`.\n    - Extract the `libduckdb.so` file to `/usr/local/lib`.\n\n    ```sh\n    unzip libduckdb-linux-amd64.zip -d libduckdb\n    sudo mv libduckdb/duckdb.* /usr/local/include/\n    sudo mv libduckdb/libduckdb.so /usr/local/lib\n    ```\n\n4. To create the necessary link, run `ldconfig` as root:\n\n    ```sh\n    sudo ldconfig /usr/local/lib # adding a --verbose flag is optional - but this will let you know if the libduckdb.so library has been linked\n    ```\n\n## Pre-requisite setup (macOS):\n\nUsing `brew install` is recommended.\n\n```sh\nbrew install duckdb\n```\n\n## Pre-requisite setup (Windows):\n\nUsing [Ruby + Devkit](https://rubyinstaller.org/downloads/) is recommended.\n\n1. Download libduckdb-windows-amd64.zip from [DuckDB](https://github.com/duckdb/duckdb/releases) and extract it.\n2. Copy `duckdb.dll` into `C:\\Windows\\System32`\n\n## How to install\n\n```sh\ngem install duckdb\n```\n\nAfter you've run the above pre-requisite setup, this should work fine.\n\nIf it doesn't, you may have to specify the location of the C header and library files:\n\n```sh\ngem install duckdb -- --with-duckdb-include=/duckdb_header_directory --with-duckdb-lib=/duckdb_library_directory\n```\n\n## Usage\n\nThe followings are some examples, for more detailed information, please refer to the [documentation](https://suketa.github.io/ruby-duckdb/index.html).\n\n```ruby\nrequire 'duckdb'\n\ndb = DuckDB::Database.open # database in memory\ncon = db.connect\n\ncon.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')\n\ncon.query(\"INSERT into users VALUES(1, 'Alice')\")\ncon.query(\"INSERT into users VALUES(2, 'Bob')\")\ncon.query(\"INSERT into users VALUES(3, 'Cathy')\")\n\nresult = con.query('SELECT * from users')\nresult.each do |row|\n  puts row\nend\n```\n\nOr, you can use block.\n\n```ruby\nrequire 'duckdb'\n\nDuckDB::Database.open do |db|\n  db.connect do |con|\n    con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')\n\n    con.query(\"INSERT into users VALUES(1, 'Alice')\")\n    con.query(\"INSERT into users VALUES(2, 'Bob')\")\n    con.query(\"INSERT into users VALUES(3, 'Cathy')\")\n\n    result = con.query('SELECT * from users')\n    result.each do |row|\n      puts row\n    end\n  end\nend\n```\n\n### Using bind variables\n\nYou can use bind variables.\n\n```ruby\ncon.query('SELECT * FROM users WHERE name = ? AND email = ?', 'Alice', 'alice@example.com')\n# or\ncon.query('SELECT * FROM users WHERE name = $name AND email = $email', name: 'Alice', email: 'alice@example.com')\n```\n### Using prepared statement\n\nYou can use prepared statement. Prepared statement object is created by `Connection#prepare` method or `DuckDB::PreparedStatement.new`.\n\n```ruby\nstmt = con.prepare('SELECT * FROM users WHERE name = $name AND email = $email')\n# or\n# stmt = con.prepared_statement('SELECT * FROM users WHERE name = $name AND email = $email')\n# or\n# stmt = DuckDB::PreparedStatement.new(con, 'SELECT * FROM users WHERE name = $name AND email = $email')\nstmt.bind(name: 'Alice', email: 'alice@example.com')\nresult = stmt.execute\nstmt.destroy\n```\nYou must call `PreparedStatement#destroy` method after using prepared statement. Otherwise, automatically destroyed\nwhen the PreparedStatement object is garbage collected.\n\nInstead of calling `PreparedStatement#destroy`, you can use block.\n\n```ruby\nresult = con.prepare('SELECT * FROM users WHERE name = $name AND email = $email') do |stmt|\n           stmt.bind(name: 'Alice', email: 'alice@example.com')\n           stmt.execute\n         end\n```\n\n### Using async query\n\nYou can use async query.\n\n```ruby\npending_result = con.async_query('SLOW QUERY')\npending_result.execute_task while pending_result.state == :not_ready\n\nresult = pending_result.execute_pending\nresult.each.first\n```\n\nHere is [the benchmark](./benchmark/async_query.rb).\n\n### Using BLOB column\n\nUse `DuckDB::Blob.new` or `my_string.force_encoding(Encoding::BINARY)`.\n\n```ruby\nrequire 'duckdb'\n\nDuckDB::Database.open do |db|\n  db.connect do |con|\n    con.query('CREATE TABLE blob_table (binary_data BLOB)')\n    stmt = DuckDB::PreparedStatement.new(con, 'INSERT INTO blob_table VALUES ($1)')\n\n    stmt.bind(1, DuckDB::Blob.new(\"\\0\\1\\2\\3\\4\\5\"))\n    # or\n    # stmt.bind(1, \"\\0\\1\\2\\3\\4\\5\".force_encoding(Encoding::BINARY))\n    stmt.execute\n\n    result = con.query('SELECT binary_data FROM blob_table')\n    puts result.first.first\n  end\nend\n```\n\n### Appender\n\nAppender class provides Ruby interface of [DuckDB Appender](https://duckdb.org/docs/data/appender)\n\n```ruby\nrequire 'duckdb'\nrequire 'benchmark'\n\ndef insert\n  DuckDB::Database.open do |db|\n    db.connect do |con|\n      con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')\n\n      10000.times do\n        con.query(\"INSERT into users VALUES(1, 'Alice')\")\n      end\n    end\n  end\nend\n\ndef prepare\n  DuckDB::Database.open do |db|\n    db.connect do |con|\n      con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')\n      stmt = con.prepared_statement('INSERT INTO users VALUES($1, $2)')\n\n      10000.times do\n        stmt.bind(1, 1)\n        stmt.bind(2, 'Alice')\n        stmt.execute\n      end\n    end\n  end\nend\n\ndef append\n  DuckDB::Database.open do |db|\n    db.connect do |con|\n      con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')\n      appender = con.appender('users')\n\n      10000.times do\n        appender.append(1)\n        appender.append('Alice')\n        appender.end_row\n      end\n\n      appender.flush\n    end\n  end\nend\n\nBenchmark.bm(8) do |x|\n  x.report('insert') { insert }\n  x.report('prepare') { prepare }\n  x.report('append') { append }\nend\n\n# =\u003e\n#                user     system      total        real\n# insert     0.637439   0.000000   0.637439 (  0.637486 )\n# prepare    0.230457   0.000000   0.230457 (  0.230460 )\n# append     0.012666   0.000000   0.012666 (  0.012670 )\n```\n\n### Configuration\n\nConfig class provides Ruby interface of [DuckDB configuration](https://duckdb.org/docs/api/c/config).\n\n```ruby\nrequire 'duckdb'\n\nconfig = DuckDB::Config.new\nconfig['default_order'] = 'DESC'\n\ndb = DuckDB::Database.open(nil, config)\n\ncon = db.connect\ncon.query('CREATE TABLE numbers (number INTEGER)')\ncon.query('INSERT INTO numbers VALUES (2), (1), (4), (3)')\n\n# number is ordered by descending\nres = con.query('SELECT number FROM numbers ORDER BY number')\nres.first.first # =\u003e 4\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuketa%2Fruby-duckdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsuketa%2Fruby-duckdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuketa%2Fruby-duckdb/lists"}