Skip to content

add DuckDB::LogicalType.resolve#1127

Merged
suketa merged 1 commit intomainfrom
logical_type_resolve
Mar 3, 2026
Merged

add DuckDB::LogicalType.resolve#1127
suketa merged 1 commit intomainfrom
logical_type_resolve

Conversation

@suketa
Copy link
Owner

@suketa suketa commented Mar 3, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a resolver method for DuckDB::LogicalType that dynamically resolves type symbols to their corresponding instances with clear error messaging for unsupported types.
  • Tests

    • Added comprehensive test coverage for the LogicalType resolver method, validating successful type resolution and error handling for invalid inputs.

@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

A new resolve(symbol) class method is added to DuckDB::LogicalType that maps symbol names to their corresponding LogicalType instances, along with comprehensive tests and changelog documentation.

Changes

Cohort / File(s) Summary
Type Resolver Implementation
lib/duckdb/logical_type.rb
Introduces resolve(symbol) class method that uppercases the given symbol, looks up the corresponding LogicalType constant, and raises ArgumentError if the type is not found.
Resolver Tests
test/duckdb_test/logical_type_test.rb
Adds comprehensive test coverage for the new resolve method, validating successful resolution for all known types and error handling for invalid symbols.
Documentation
CHANGELOG.md
Updates changelog to document the addition of DuckDB::LogicalType.resolve in the Unreleased section.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 A symbol hops into resolve's den,
Uppercased swift, looked up again,
Constants gleam in their nested home,
No unknown types dare to roam! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 title 'add DuckDB::LogicalType.resolve' directly and clearly describes the main change—adding a new resolver method to the DuckDB::LogicalType class, which is the primary focus of the changeset.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch logical_type_resolve

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

@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)
test/duckdb_test/logical_type_test.rb (1)

166-170: Add a regression case for inherited constants.

Please include an assertion like resolve(:env) raising ArgumentError to guard against ancestor constant lookup regressions.

✅ Suggested test addition
     def test_s_resolve_with_invalid_symbol
       assert_raises(ArgumentError) do
         DuckDB::LogicalType.resolve(:invalid_type)
       end
+      assert_raises(ArgumentError) do
+        DuckDB::LogicalType.resolve(:env)
+      end
     end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/duckdb_test/logical_type_test.rb` around lines 166 - 170, Add a
regression assertion to the test_s_resolve_with_invalid_symbol case so that
inherited constants are not resolved via ancestor lookup: within the test method
(test_s_resolve_with_invalid_symbol) add an assert_raises(ArgumentError) that
calls DuckDB::LogicalType.resolve(:env) to ensure resolving :env raises
ArgumentError and guards against ancestor constant lookup regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/duckdb/logical_type.rb`:
- Around line 58-61: The resolve method in DuckDB::LogicalType is currently
using const_get with inherited lookup, which can return unrelated constants from
ancestors; change resolve(symbol) to perform a non-inherited lookup (e.g., use
const_defined?(symbol.upcase, false) and then const_get(symbol.upcase, false) or
const_get with inherit: false) so that only constants defined directly on
DuckDB::LogicalType are returned and otherwise raise the existing ArgumentError.

---

Nitpick comments:
In `@test/duckdb_test/logical_type_test.rb`:
- Around line 166-170: Add a regression assertion to the
test_s_resolve_with_invalid_symbol case so that inherited constants are not
resolved via ancestor lookup: within the test method
(test_s_resolve_with_invalid_symbol) add an assert_raises(ArgumentError) that
calls DuckDB::LogicalType.resolve(:env) to ensure resolving :env raises
ArgumentError and guards against ancestor constant lookup regressions.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74fe4b5 and 7cf4f05.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • lib/duckdb/logical_type.rb
  • test/duckdb_test/logical_type_test.rb

Comment on lines +58 to +61
def resolve(symbol)
DuckDB::LogicalType.const_get(symbol.upcase)
rescue NameError
raise ArgumentError, "Unknown logical type symbol: #{symbol}"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Ruby Module#const_get inherit parameter behavior documentation

💡 Result:

Module#const_get(name, inherit = true) controls whether Ruby searches ancestors when resolving the constant name:

  • Default (inherit = true): Ruby looks for the constant in the receiver, and if not found, also searches the receiver’s ancestors. Additionally, if the receiver is a Module, Ruby also searches Object (and its ancestors). (docs.ruby-lang.org)
  • inherit = false: Ruby only checks the receiver itself (no ancestor / Object lookup). (docs.ruby-lang.org)
  • Qualified names ("A::B::C"): Ruby resolves the path step-by-step, and the inherit flag is applied at each step (so inherit: false can prevent a later segment from being found via inheritance). (docs.ruby-lang.org)

Citations:


🏁 Script executed:

# Check the file to see the actual implementation
cat -n lib/duckdb/logical_type.rb | head -70

Repository: suketa/ruby-duckdb

Length of output: 2161


🏁 Script executed:

# Search for any tests related to LogicalType.resolve
find . -type f -name "*.rb" | xargs grep -l "LogicalType.resolve" 2>/dev/null | head -5

Repository: suketa/ruby-duckdb

Length of output: 101


🏁 Script executed:

# Check if there are constants defined in DuckDB::LogicalType
grep -n "const_get\|::.*=" lib/duckdb/logical_type.rb | head -20

Repository: suketa/ruby-duckdb

Length of output: 117


🏁 Script executed:

# Check the test file to understand how resolve is being tested
cat -n ./test/duckdb_test/logical_type_test.rb

Repository: suketa/ruby-duckdb

Length of output: 12546


🏁 Script executed:

# Test if the issue is real by checking what Object::ENV resolves to
python3 << 'EOF'
# Simulate the behavior in Ruby to understand the issue
# const_get with inherit=true on a Module will search Object's constants

# Let's check if there are any constants like ENV that could conflict
import subprocess
result = subprocess.run(['ruby', '-e', '''
  module TestModule
  end
  
  # This will find Object::ENV because inherit=true (default)
  begin
    result = TestModule.const_get("ENV")
    puts "Found: #{result.class} - #{result.inspect[0..50]}"
  rescue NameError => e
    puts "NameError: #{e.message}"
  end
  
  # This should fail because inherit=false
  begin
    result = TestModule.const_get("ENV", false)
    puts "Found with inherit=false: #{result.inspect}"
  rescue NameError => e
    puts "NameError with inherit=false: #{e.message}"
  end
'''], capture_output=True, text=True)
print(result.stdout)
print(result.stderr)
EOF

Repository: suketa/ruby-duckdb

Length of output: 200


🏁 Script executed:

# Check if DuckDB::LogicalType has any constants defined dynamically
grep -A 5 -B 5 "const_set" lib/duckdb/logical_type.rb | head -15

Repository: suketa/ruby-duckdb

Length of output: 404


Disable inherited constant lookup in resolve to prevent returning unrelated constants.

const_get with the default inherit=true searches ancestors and Object, so symbols like :env can resolve to Object::ENV instead of raising ArgumentError. This violates the contract that only DuckDB::LogicalType constants should be returned.

💡 Suggested fix
     class << self
       def resolve(symbol)
-        DuckDB::LogicalType.const_get(symbol.upcase)
+        DuckDB::LogicalType.const_get(symbol.to_s.upcase, false)
       rescue NameError
         raise ArgumentError, "Unknown logical type symbol: #{symbol}"
       end
     end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def resolve(symbol)
DuckDB::LogicalType.const_get(symbol.upcase)
rescue NameError
raise ArgumentError, "Unknown logical type symbol: #{symbol}"
def resolve(symbol)
DuckDB::LogicalType.const_get(symbol.to_s.upcase, false)
rescue NameError
raise ArgumentError, "Unknown logical type symbol: #{symbol}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/duckdb/logical_type.rb` around lines 58 - 61, The resolve method in
DuckDB::LogicalType is currently using const_get with inherited lookup, which
can return unrelated constants from ancestors; change resolve(symbol) to perform
a non-inherited lookup (e.g., use const_defined?(symbol.upcase, false) and then
const_get(symbol.upcase, false) or const_get with inherit: false) so that only
constants defined directly on DuckDB::LogicalType are returned and otherwise
raise the existing ArgumentError.

@suketa suketa merged commit 9041a3b into main Mar 3, 2026
40 of 41 checks passed
@suketa suketa deleted the logical_type_resolve branch March 3, 2026 11:59
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.

1 participant