Skip to content

Add DuckDB::Connection#register_logical_type#1241

Merged
suketa merged 3 commits intosuketa:mainfrom
otegami:feature/register-logical-type
Apr 7, 2026
Merged

Add DuckDB::Connection#register_logical_type#1241
suketa merged 3 commits intosuketa:mainfrom
otegami:feature/register-logical-type

Conversation

@otegami
Copy link
Copy Markdown
Contributor

@otegami otegami commented Apr 6, 2026

GitHub: fix GH-940

In this PR, we add DuckDB::Connection#register_logical_type to register a custom logical type with a connection by wrapping the following C API:

The method accepts a DuckDB::LogicalType instance that must have an alias set via LogicalType#alias= before registration. The alias becomes the SQL type name.

The third parameter duckdb_create_type_info is reserved for future use in the DuckDB C API and is passed as NULL.

Summary by CodeRabbit

New Features

  • Added support for registering custom logical types with DuckDB connections. Logical types must have an alias configured before registration and may raise errors during the registration process.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b41c7185-ec49-4eee-8bfc-053a7b6108aa

📥 Commits

Reviewing files that changed from the base of the PR and between 31af81b and adc6928.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • ext/duckdb/connection.c
  • lib/duckdb/connection.rb
  • test/duckdb_test/connection_test.rb
🚧 Files skipped from review as they are similar to previous changes (3)
  • CHANGELOG.md
  • lib/duckdb/connection.rb
  • ext/duckdb/connection.c

📝 Walkthrough

Walkthrough

This pull request adds support for registering custom logical types with DuckDB connections. The implementation includes a public Ruby method with type validation, a private C wrapper that calls the DuckDB C API, lifecycle management to keep logical type objects alive, and comprehensive test coverage for enum and struct type registration scenarios.

Changes

Cohort / File(s) Summary
Documentation
CHANGELOG.md
Added changelog entry for the new DuckDB::Connection#register_logical_type method.
Public API
lib/duckdb/connection.rb
Added public register_logical_type(logical_type) method with DuckDB::LogicalType validation and delegation to internal C implementation.
C Extension
ext/duckdb/connection.c
Implemented private _register_logical_type(logical_type) method that wraps DuckDB's C API, manages object lifecycle via registered_functions, and handles registration errors.
Tests
test/duckdb_test/connection_test.rb
Added four test cases: enum type registration with alias, struct type registration with alias, error case for missing alias, and error case for invalid argument type.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Ruby Client
    participant RubyAPI as Connection<br/>(Ruby)
    participant CExtension as _register_logical_type<br/>(C)
    participant DuckDBAPI as DuckDB C API

    Client->>RubyAPI: register_logical_type(logical_type)
    RubyAPI->>RubyAPI: Validate LogicalType argument
    RubyAPI->>CExtension: _register_logical_type(logical_type)
    CExtension->>CExtension: Extract connection & payload
    CExtension->>DuckDBAPI: duckdb_register_logical_type(...)
    alt Registration succeeds
        DuckDBAPI-->>CExtension: Success
        CExtension->>CExtension: Append to registered_functions<br/>(keep object alive)
        CExtension-->>RubyAPI: Return
        RubyAPI-->>Client: Success
    else Registration fails
        DuckDBAPI-->>CExtension: Error
        CExtension-->>RubyAPI: Raise eDuckDBError
        RubyAPI-->>Client: Raise DuckDB::Error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • suketa

Poem

🐰✨ A logical type now finds its place,
Registered swift with Ruby's grace,
From enum to struct, the types align,
DuckDB connections—oh, how they shine!
Registration magic, clean and neat,
Custom types make queries complete! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and directly summarizes the main change: adding a new method DuckDB::Connection#register_logical_type.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
lib/duckdb/connection.rb (1)

154-158: Pre-validate logical_type.alias before native registration.

The method documents alias as required, but currently relies on native failure. A Ruby-side precheck gives a clearer, immediate contract error.

💡 Suggested refinement
 def register_logical_type(logical_type)
   raise TypeError, "#{logical_type.class} is not a DuckDB::LogicalType" unless logical_type.is_a?(LogicalType)
+  if logical_type.alias.nil? || logical_type.alias.empty?
+    raise ArgumentError, 'logical_type.alias must be set before registration'
+  end
 
   _register_logical_type(logical_type)
 end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/duckdb/connection.rb` around lines 154 - 158, The register_logical_type
method should validate that logical_type.alias exists and is a proper String
before calling _register_logical_type; add a pre-check in register_logical_type
that raises ArgumentError (or TypeError if you prefer consistency) when
logical_type.alias is nil, empty, or not a String, referencing the LogicalType
instance and its alias attribute, then call _register_logical_type only after
the alias validation passes to provide a clear Ruby-side contract error instead
of relying on native failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Line 21: Move the changelog entry that adds
"DuckDB::Connection#register_logical_type" out of the released 1.5.1.1 section
and place it under the Unreleased section header; specifically locate the line
containing "add `DuckDB::Connection#register_logical_type` to register a custom
logical type with a connection." and cut/paste it into the Unreleased section so
it remains listed as not-yet-released.

---

Nitpick comments:
In `@lib/duckdb/connection.rb`:
- Around line 154-158: The register_logical_type method should validate that
logical_type.alias exists and is a proper String before calling
_register_logical_type; add a pre-check in register_logical_type that raises
ArgumentError (or TypeError if you prefer consistency) when logical_type.alias
is nil, empty, or not a String, referencing the LogicalType instance and its
alias attribute, then call _register_logical_type only after the alias
validation passes to provide a clear Ruby-side contract error instead of relying
on native failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 76330f8c-1249-46e5-a446-c514e7f62b32

📥 Commits

Reviewing files that changed from the base of the PR and between 8d98110 and 24e0784.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • ext/duckdb/connection.c
  • lib/duckdb/connection.rb
  • test/duckdb_test/connection_test.rb

Comment thread CHANGELOG.md Outdated
@otegami otegami force-pushed the feature/register-logical-type branch from 24e0784 to 7ff0c76 Compare April 6, 2026 09:09
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lib/duckdb/connection.rb (1)

154-158: Pre-validate logical type alias before calling native registration.

On Line 157, missing alias currently fails in C with a generic registration error. A Ruby-side alias check gives a clearer, immediate failure reason.

♻️ Proposed refinement
 def register_logical_type(logical_type)
   raise TypeError, "#{logical_type.class} is not a DuckDB::LogicalType" unless logical_type.is_a?(LogicalType)
+  alias_name = logical_type.alias
+  if alias_name.nil? || alias_name.empty?
+    raise DuckDB::Error, 'LogicalType alias must be set before registration'
+  end
 
   _register_logical_type(logical_type)
 end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/duckdb/connection.rb` around lines 154 - 158, The register_logical_type
method currently calls _register_logical_type without verifying that
logical_type has a valid alias, which causes a generic native error; before
calling _register_logical_type, add a Ruby-side prevalidation that the passed
logical_type (instance of LogicalType) responds to and returns a non-empty alias
(e.g., check logical_type.alias or a suitable accessor) and raise a clear
TypeError/ArgumentError if missing or blank, referencing register_logical_type,
LogicalType, and _register_logical_type to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/duckdb/connection.rb`:
- Around line 154-158: The register_logical_type method currently calls
_register_logical_type without verifying that logical_type has a valid alias,
which causes a generic native error; before calling _register_logical_type, add
a Ruby-side prevalidation that the passed logical_type (instance of LogicalType)
responds to and returns a non-empty alias (e.g., check logical_type.alias or a
suitable accessor) and raise a clear TypeError/ArgumentError if missing or
blank, referencing register_logical_type, LogicalType, and
_register_logical_type to locate the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7dfe1d50-ff1f-4ca2-ae07-d81076d53968

📥 Commits

Reviewing files that changed from the base of the PR and between 24e0784 and 7ff0c76.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • ext/duckdb/connection.c
  • lib/duckdb/connection.rb
  • test/duckdb_test/connection_test.rb
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • ext/duckdb/connection.c
  • test/duckdb_test/connection_test.rb

@otegami otegami force-pushed the feature/register-logical-type branch from 7ff0c76 to f9dd52c Compare April 7, 2026 06:13
@otegami otegami changed the title feat: add DuckDB::Connection#register_logical_type Add DuckDB::Connection#register_logical_type Apr 7, 2026
Copy link
Copy Markdown
Owner

@suketa suketa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your great work!

I commented.

Comment thread ext/duckdb/connection.c Outdated
* mood.alias = 'mood'
* con.register_logical_type(mood)
* con.query('CREATE TABLE t (m mood)')
*/
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is private method implementation. so use /* nodoc */ instead documents

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix: 1815e5d Sure!

Comment thread ext/duckdb/connection.c Outdated
@otegami otegami force-pushed the feature/register-logical-type branch from f9dd52c to 31af81b Compare April 7, 2026 09:22
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lib/duckdb/connection.rb (1)

140-158: Implementation is correct and follows existing patterns.

The type validation using TypeError is consistent with register_scalar_function_set at line 226. The documentation is well-structured with YARD tags and accurately reflects the C API behavior—testing confirms that DuckDB::Error is properly raised when the logical type has no alias set.

No changes required.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/duckdb/connection.rb` around lines 140 - 158, No changes required: the
register_logical_type method correctly validates the argument type using
LogicalType (raising TypeError) and delegates to _register_logical_type, and the
documentation/YARD tags and error behavior match existing patterns (see
register_logical_type, LogicalType, and _register_logical_type).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/duckdb/connection.rb`:
- Around line 140-158: No changes required: the register_logical_type method
correctly validates the argument type using LogicalType (raising TypeError) and
delegates to _register_logical_type, and the documentation/YARD tags and error
behavior match existing patterns (see register_logical_type, LogicalType, and
_register_logical_type).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9511f228-2704-4d28-bf5d-38387fa26e0a

📥 Commits

Reviewing files that changed from the base of the PR and between f9dd52c and 31af81b.

📒 Files selected for processing (5)
  • .rubocop.yml
  • CHANGELOG.md
  • ext/duckdb/connection.c
  • lib/duckdb/connection.rb
  • test/duckdb_test/connection_test.rb
✅ Files skipped from review due to trivial changes (3)
  • .rubocop.yml
  • CHANGELOG.md
  • test/duckdb_test/connection_test.rb
🚧 Files skipped from review as they are similar to previous changes (1)
  • ext/duckdb/connection.c

@otegami
Copy link
Copy Markdown
Contributor Author

otegami commented Apr 7, 2026

Done: I will resolve this conflict now.

otegami added 3 commits April 7, 2026 19:19
refs: suketaGH-940

In this PR, we add `DuckDB::Connection#register_logical_type` to register
a custom logical type with a connection by wrapping the following C API:

- [duckdb_state duckdb_register_logical_type(duckdb_connection con, duckdb_logical_type type, duckdb_create_type_info info);](https://duckdb.org/docs/current/clients/c/api#duckdb_register_logical_type)

The method accepts a `DuckDB::LogicalType` instance that must have an alias
set via `LogicalType#alias=` before registration. The alias becomes the SQL
type name.

The third parameter `duckdb_create_type_info` is reserved for future use in the DuckDB C API and is passed as `NULL`.
@otegami otegami force-pushed the feature/register-logical-type branch from 31af81b to adc6928 Compare April 7, 2026 10:19
Copy link
Copy Markdown
Owner

@suketa suketa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@suketa suketa merged commit 2b3a19d into suketa:main Apr 7, 2026
41 checks passed
@otegami otegami deleted the feature/register-logical-type branch April 7, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DuckDB::Column duckdb_create_xxxx_type

2 participants