Class: DuckDB::LogicalType

Inherits:
Object
  • Object
show all
Defined in:
lib/duckdb/logical_type.rb,
ext/duckdb/logical_type.c

Overview

rubocop:disable Metrics/ClassLength

Constant Summary collapse

RANGE_DECIMAL_WIDTH =
1..38

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type_id_arg) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'ext/duckdb/logical_type.c', line 64

static VALUE initialize(VALUE self, VALUE type_id_arg) {
    rubyDuckDBLogicalType *ctx;
    duckdb_type type = (duckdb_type)NUM2INT(type_id_arg);
    duckdb_logical_type new_logical_type;

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);

    if (ctx->logical_type) {
        duckdb_destroy_logical_type(&(ctx->logical_type));
    }

    new_logical_type = duckdb_create_logical_type(type);

    if (!new_logical_type || duckdb_get_type_id(new_logical_type) == DUCKDB_TYPE_INVALID) {
        if (new_logical_type) {
            duckdb_destroy_logical_type(&new_logical_type);
        }
        rb_raise(rb_eArgError, "Invalid or unsupported logical type ID: %d", type);
    }

    ctx->logical_type = new_logical_type;

    return self;
}

Class Method Details

.create_array(type, size) ⇒ Object

Creates an array logical type with the given child type and size.

The type argument can be a symbol or a DuckDB::LogicalType instance. The size argument specifies the fixed size of the array.

require 'duckdb'

array_type = DuckDB::LogicalType.create_array(:integer, 3)
array_type.type #=> :array
array_type.child_type.type #=> :integer
array_type.size #=> 3


82
83
84
# File 'lib/duckdb/logical_type.rb', line 82

def create_array(type, size)
  _create_array_type(LogicalType.resolve(type), size)
end

.create_decimal(width, scale) ⇒ Object

Creates a decimal logical type with the given width and scale.

require 'duckdb'

decimal_type = DuckDB::LogicalType.create_decimal(18, 3)
decimal_type.type #=> :decimal
decimal_type.width #=> 18
decimal_type.scale #=> 3

Raises:



173
174
175
176
177
178
# File 'lib/duckdb/logical_type.rb', line 173

def create_decimal(width, scale)
  raise DuckDB::Error, 'width must be between 1 and 38' unless RANGE_DECIMAL_WIDTH.cover?(width)
  raise DuckDB::Error, "scale must be between 0 and width(#{width})" unless (0..width).cover?(scale)

  _create_decimal_type(width, scale)
end

.create_enum(*members) ⇒ Object

Creates an enum logical type with the given members.

Each member must be a String representing an enum member.

require 'duckdb'

enum_type = DuckDB::LogicalType.create_enum('happy', 'sad', 'neutral')
enum_type.type #=> :enum
enum_type.dictionary_size #=> 3
enum_type.dictionary_value_at(0) #=> "happy"


161
162
163
# File 'lib/duckdb/logical_type.rb', line 161

def create_enum(*members)
  _create_enum_type(members.map(&:to_s))
end

.create_list(type) ⇒ Object

Creates a list logical type with the given child type.

The type argument can be a symbol or a DuckDB::LogicalType instance.

require 'duckdb'

list_type = DuckDB::LogicalType.create_list(:integer)
list_type.type #=> :list
list_type.child_type.type #=> :integer

nested_list = DuckDB::LogicalType.create_list(list_type)
nested_list.child_type.type #=> :list


98
99
100
# File 'lib/duckdb/logical_type.rb', line 98

def create_list(type)
  _create_list_type(LogicalType.resolve(type))
end

.create_map(key_type, value_type) ⇒ Object

Creates a map logical type with the given key and value types.

The key_type and value_type arguments can be symbols or DuckDB::LogicalType instances.

require 'duckdb'

map_type = DuckDB::LogicalType.create_map(:integer, :varchar)
map_type.type #=> :map
map_type.key_type.type #=> :integer
map_type.value_type.type #=> :varchar


113
114
115
# File 'lib/duckdb/logical_type.rb', line 113

def create_map(key_type, value_type)
  _create_map_type(LogicalType.resolve(key_type), LogicalType.resolve(value_type))
end

.create_struct(**members) ⇒ Object

Creates a struct logical type with the given member names and types.

The keyword arguments map member names to types. Each type can be a symbol or a DuckDB::LogicalType instance.

require 'duckdb'

struct_type = DuckDB::LogicalType.create_struct(name: :varchar, age: :integer)
struct_type.type #=> :struct
struct_type.child_count #=> 2
struct_type.child_name_at(0) #=> "name"
struct_type.child_type_at(0).type #=> :varchar


146
147
148
149
# File 'lib/duckdb/logical_type.rb', line 146

def create_struct(**members)
  resolved = members.transform_values { |v| LogicalType.resolve(v) }
  _create_struct_type(resolved)
end

.create_union(**members) ⇒ Object

Creates a union logical type with the given member names and types.

The keyword arguments map member names to types. Each type can be a symbol or a DuckDB::LogicalType instance.

require 'duckdb'

union_type = DuckDB::LogicalType.create_union(num: :integer, str: :varchar)
union_type.type #=> :union
union_type.member_count #=> 2
union_type.member_name_at(0) #=> "num"
union_type.member_type_at(0).type #=> :integer


129
130
131
132
# File 'lib/duckdb/logical_type.rb', line 129

def create_union(**members)
  resolved = members.transform_values { |v| LogicalType.resolve(v) }
  _create_union_type(resolved)
end

.resolve(symbol) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'lib/duckdb/logical_type.rb', line 61

def resolve(symbol)
  return symbol if symbol.is_a?(DuckDB::LogicalType)

  raise_resolve_error(symbol) unless symbol.respond_to?(:upcase)

  DuckDB::LogicalType.const_get(symbol.upcase)
rescue NameError
  raise_resolve_error(symbol)
end

Instance Method Details

#logical_type.internal_typeSymbol

Returns the logical type’s internal type.

Returns:

  • (Symbol)


340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'ext/duckdb/logical_type.c', line 340

static VALUE duckdb_logical_type__internal_type(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    duckdb_type type_id;
    duckdb_type internal_type_id;

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);

    type_id = duckdb_get_type_id(ctx->logical_type);
    switch (type_id) {
        case DUCKDB_TYPE_DECIMAL:
            internal_type_id = duckdb_decimal_internal_type(ctx->logical_type);
            break;
        case DUCKDB_TYPE_ENUM:
            internal_type_id = duckdb_enum_internal_type(ctx->logical_type);
            break;
        default:
            internal_type_id = DUCKDB_TYPE_INVALID;
    }

    return INT2FIX(internal_type_id);
}

#logical_type.child_countInteger

Returns the number of children of a struct type, otherwise 0.

Returns:

  • (Integer)


135
136
137
138
139
# File 'ext/duckdb/logical_type.c', line 135

static VALUE duckdb_logical_type_child_count(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    return INT2FIX(duckdb_struct_type_child_count(ctx->logical_type));
}

#logical_type.child_name(index) ⇒ String

Returns the name of the struct child at the specified index.

Returns:

  • (String)


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'ext/duckdb/logical_type.c', line 148

static VALUE duckdb_logical_type_child_name_at(VALUE self, VALUE cidx) {
    rubyDuckDBLogicalType *ctx;
    VALUE cname;
    const char *child_name;
    idx_t idx = NUM2ULL(cidx);

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);

    child_name = duckdb_struct_type_child_name(ctx->logical_type, idx);
    if (child_name == NULL) {
        rb_raise(eDuckDBError, "fail to get name of %llu child", (unsigned long long)idx);
    }
    cname = rb_str_new_cstr(child_name);
    duckdb_free((void *)child_name);
    return cname;
}

#logical_type.child_typeDuckDB::LogicalType

Returns the child logical type for list and map types, otherwise nil.

Returns:



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'ext/duckdb/logical_type.c', line 172

static VALUE duckdb_logical_type_child_type(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    duckdb_type type_id;
    duckdb_logical_type child_logical_type;
    VALUE logical_type = Qnil;

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    type_id = duckdb_get_type_id(ctx->logical_type);

    switch(type_id) {
        case DUCKDB_TYPE_LIST:
        case DUCKDB_TYPE_MAP:
            child_logical_type = duckdb_list_type_child_type(ctx->logical_type);
            logical_type = rbduckdb_create_logical_type(child_logical_type);
            break;
        case DUCKDB_TYPE_ARRAY:
            child_logical_type = duckdb_array_type_child_type(ctx->logical_type);
            logical_type = rbduckdb_create_logical_type(child_logical_type);
            break;
        default:
            logical_type = Qnil;
    }
    return logical_type;
}

#logical_type.child_type_at(index) ⇒ DuckDB::LogicalType

Returns the child logical type for struct types at the specified index as a DuckDB::LogicalType object.

Returns:



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'ext/duckdb/logical_type.c', line 205

static VALUE duckdb_logical_type_child_type_at(VALUE self, VALUE cidx) {
    rubyDuckDBLogicalType *ctx;
    duckdb_logical_type struct_child_type;
    idx_t idx = NUM2ULL(cidx);

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);

    struct_child_type = duckdb_struct_type_child_type(ctx->logical_type, idx);
    if (struct_child_type == NULL) {
        rb_raise(eDuckDBError,
                 "Failed to get the struct child type at index %llu",
                 (unsigned long long)idx);
    }

    return rbduckdb_create_logical_type(struct_child_type);
}

#logical_type.dictionary_sizeInteger

Returns the dictionary size of the enum type.

Returns:

  • (Integer)


369
370
371
372
373
# File 'ext/duckdb/logical_type.c', line 369

static VALUE duckdb_logical_type_dictionary_size(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    return INT2FIX(duckdb_enum_dictionary_size(ctx->logical_type));
}

#logical_type.dictionary_value_at(index) ⇒ String

Returns the dictionary value at the specified index.

Returns:

  • (String)


382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'ext/duckdb/logical_type.c', line 382

static VALUE duckdb_logical_type_dictionary_value_at(VALUE self, VALUE didx) {
    rubyDuckDBLogicalType *ctx;
    VALUE dvalue;
    const char *dict_value;
    idx_t idx = NUM2ULL(didx);

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);

    dict_value = duckdb_enum_dictionary_value(ctx->logical_type, idx);
    if (dict_value == NULL) {
        rb_raise(eDuckDBError, "fail to get dictionary value of %llu", (unsigned long long)idx);
    }
    dvalue = rb_utf8_str_new_cstr(dict_value);
    duckdb_free((void *)dict_value);
    return dvalue;
}

#each_child_nameObject

Iterates over each struct child name.

When a block is provided, this method yields each struct child name in order. It also returns the total number of children yielded.

struct_logical_type.each_child_name do |name|
  puts "Struct child: #{name}"
end

If no block is given, an Enumerator is returned, which can be used to retrieve all child names.

names = struct_logical_type.each_child_name.to_a
# => ["child1", "child2"]


280
281
282
283
284
285
286
# File 'lib/duckdb/logical_type.rb', line 280

def each_child_name
  return to_enum(__method__) { child_count } unless block_given?

  child_count.times do |i|
    yield child_name_at(i)
  end
end

#each_child_typeObject

Iterates over each struct child type.

When a block is provided, this method yields each struct child type in order. It also returns the total number of children yielded.

struct_logical_type.each_child_type do |logical_type|
  puts "Struct child type: #{logical_type.type}"
end

If no block is given, an Enumerator is returned, which can be used to retrieve all child logical types.

types = struct_logical_type.each_child_type.map(&:type)
# => [:integer, :varchar]


302
303
304
305
306
307
308
# File 'lib/duckdb/logical_type.rb', line 302

def each_child_type
  return to_enum(__method__) { child_count } unless block_given?

  child_count.times do |i|
    yield child_type_at(i)
  end
end

#each_dictionary_valueObject

Iterates over each enum dictionary value.

When a block is provided, this method yields each enum dictionary value in order. It also returns the total number of dictionary values yielded.

enum_logical_type.each_value do |value|
  puts "Enum value: #{value}"
end

If no block is given, an Enumerator is returned, which can be used to retrieve all enum dictionary values.

values = enum_logical_type.each_value.to_a
# => ["happy", "sad"]


324
325
326
327
328
329
330
# File 'lib/duckdb/logical_type.rb', line 324

def each_dictionary_value
  return to_enum(__method__) { dictionary_size } unless block_given?

  dictionary_size.times do |i|
    yield dictionary_value_at(i)
  end
end

#each_member_nameObject

Iterates over each union member name.

When a block is provided, this method yields each union member name in order. It also returns the total number of members yielded.

union_logical_type.each_member_name do |name|
  puts "Union member: #{name}"
end

If no block is given, an Enumerator is returned, which can be used to retrieve all member names.

names = union_logical_type.each_member_name.to_a
# => ["member1", "member2"]


236
237
238
239
240
241
242
# File 'lib/duckdb/logical_type.rb', line 236

def each_member_name
  return to_enum(__method__) { member_count } unless block_given?

  member_count.times do |i|
    yield member_name_at(i)
  end
end

#each_member_typeObject

Iterates over each union member type.

When a block is provided, this method yields each union member logical type in order. It also returns the total number of members yielded.

union_logical_type.each_member_type do |logical_type|
  puts "Union member: #{logical_type.type}"
end

If no block is given, an Enumerator is returned, which can be used to retrieve all member logical types.

names = union_logical_type.each_member_type.map(&:type)
# => [:varchar, :integer]


258
259
260
261
262
263
264
# File 'lib/duckdb/logical_type.rb', line 258

def each_member_type
  return to_enum(__method__) { member_count } unless block_given?

  member_count.times do |i|
    yield member_type_at(i)
  end
end

#logical_type.aliasString Also known as: alias

Returns the alias of the logical type.

Returns:

  • (String)


406
407
408
409
410
411
412
413
414
415
416
417
418
419
# File 'ext/duckdb/logical_type.c', line 406

static VALUE duckdb_logical_type__get_alias(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    VALUE alias = Qnil;
    const char *_alias;

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);

    _alias = duckdb_logical_type_get_alias(ctx->logical_type);
    if (_alias != NULL) {
        alias = rb_utf8_str_new_cstr(_alias);
    }
    duckdb_free((void *)_alias);
    return alias;
}

#inspectObject

:nodoc:



333
334
335
# File 'lib/duckdb/logical_type.rb', line 333

def inspect
  "<#{self.class}::#{type.upcase}>"
end

#internal_typeObject

returns logical type’s internal type symbol for Decimal or Enum types ‘:unknown` means that the logical type’s type is unknown/unsupported by ruby-duckdb. ‘:invalid` means that the logical type’s type is invalid in duckdb.

require 'duckdb'
db = DuckDB::Database.open
con = db.connect
con.query("CREATE TYPE mood AS ENUM ('happy', 'sad')")
con.query("CREATE TABLE emotions (id INTEGER, enum_col mood)")

users = con.query('SELECT * FROM emotions')
ernum_col = users.columns.find { |col| col.name == 'enum_col' }
enum_col.logical_type.internal_type #=> :utinyint


217
218
219
220
# File 'lib/duckdb/logical_type.rb', line 217

def internal_type
  type_id = _internal_type
  DuckDB::Converter::IntToSym.type_to_sym(type_id)
end

#logical_type.key_typeDuckDB::LogicalType

Returns the key logical type for map type, otherwise nil.

Returns:



242
243
244
245
246
247
248
249
250
251
# File 'ext/duckdb/logical_type.c', line 242

static VALUE duckdb_logical_type_key_type(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    duckdb_logical_type key_logical_type;
    VALUE logical_type = Qnil;

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    key_logical_type = duckdb_map_type_key_type(ctx->logical_type);
    logical_type = rbduckdb_create_logical_type(key_logical_type);
    return logical_type;
}

#logical_type.member_countInteger

Returns the member count of union type, otherwise 0.

Returns:

  • (Integer)


278
279
280
281
282
# File 'ext/duckdb/logical_type.c', line 278

static VALUE duckdb_logical_type_member_count(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    return INT2FIX(duckdb_union_type_member_count(ctx->logical_type));
}

#logical_type.member_name_at(index) ⇒ String

Returns the name of the union member at the specified index.

Returns:

  • (String)


291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'ext/duckdb/logical_type.c', line 291

static VALUE duckdb_logical_type_member_name_at(VALUE self, VALUE midx) {
    rubyDuckDBLogicalType *ctx;
    VALUE mname;
    const char *member_name;
    idx_t idx = NUM2ULL(midx);

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);

    member_name = duckdb_union_type_member_name(ctx->logical_type, idx);
    if (member_name == NULL) {
        rb_raise(eDuckDBError, "fail to get name of %llu member", (unsigned long long)idx);
    }
    mname = rb_str_new_cstr(member_name);
    duckdb_free((void *)member_name);
    return mname;
}

#logical_type.member_type_at(index) ⇒ DuckDB::LogicalType

Returns the logical type of the union member at the specified index as a DuckDB::LogicalType object.

Returns:



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'ext/duckdb/logical_type.c', line 316

static VALUE duckdb_logical_type_member_type_at(VALUE self, VALUE midx) {
    rubyDuckDBLogicalType *ctx;
    duckdb_logical_type union_member_type;
    idx_t idx = NUM2ULL(midx);

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);

    union_member_type = duckdb_union_type_member_type(ctx->logical_type, idx);
    if (union_member_type == NULL) {
        rb_raise(eDuckDBError,
                 "Failed to get the union member type at index %llu",
                 (unsigned long long)idx);
    }

    return rbduckdb_create_logical_type(union_member_type);
}

#logical_type.scaleInteger

Returns the scale of the decimal column.

Returns:

  • (Integer)


122
123
124
125
126
# File 'ext/duckdb/logical_type.c', line 122

static VALUE duckdb_logical_type_scale(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    return INT2FIX(duckdb_decimal_scale(ctx->logical_type));
}

#logical_type.aliasString Also known as: alias=

Return the set alias of the logical type.

Returns:

  • (String)


428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'ext/duckdb/logical_type.c', line 428

static VALUE duckdb_logical_type__set_alias(VALUE self, VALUE aname) {
    rubyDuckDBLogicalType *ctx;
    VALUE alias = Qnil;
    const char *_alias = StringValuePtr(aname);

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    duckdb_logical_type_set_alias(ctx->logical_type, _alias);
    if (_alias != NULL) {
        alias = rb_utf8_str_new_cstr(_alias);
    }

    return alias;
}

#logical_type.sizeInteger

Returns the size of the array column, otherwise 0.

Returns:

  • (Integer)


229
230
231
232
233
# File 'ext/duckdb/logical_type.c', line 229

static VALUE duckdb_logical_type_size(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    return INT2FIX(duckdb_array_type_array_size(ctx->logical_type));
}

#to_sObject

:nodoc:



338
339
340
# File 'lib/duckdb/logical_type.rb', line 338

def to_s
  inspect
end

#typeObject

returns logical type’s type symbol ‘:unknown` means that the logical type’s type is unknown/unsupported by ruby-duckdb. ‘:invalid` means that the logical type’s type is invalid in duckdb.

require 'duckdb'
db = DuckDB::Database.open
con = db.connect
con.query('CREATE TABLE climates (id INTEGER, temperature DECIMAIL)')

users = con.query('SELECT * FROM climates')
columns = users.columns
columns.second.logical_type.type #=> :decimal


199
200
201
202
# File 'lib/duckdb/logical_type.rb', line 199

def type
  type_id = _type
  DuckDB::Converter::IntToSym.type_to_sym(type_id)
end

#logical_type.value_typeDuckDB::LogicalType

Returns the value logical type for map type, otherwise nil.

Returns:



260
261
262
263
264
265
266
267
268
269
# File 'ext/duckdb/logical_type.c', line 260

static VALUE duckdb_logical_type_value_type(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    duckdb_logical_type value_logical_type;
    VALUE logical_type = Qnil;

    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    value_logical_type = duckdb_map_type_value_type(ctx->logical_type);
    logical_type = rbduckdb_create_logical_type(value_logical_type);
    return logical_type;
}

#logical_type.widthInteger

Returns the width of the decimal column.

Returns:

  • (Integer)


109
110
111
112
113
# File 'ext/duckdb/logical_type.c', line 109

static VALUE duckdb_logical_type_width(VALUE self) {
    rubyDuckDBLogicalType *ctx;
    TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
    return INT2FIX(duckdb_decimal_width(ctx->logical_type));
}