Module: DuckDB::Converter

Included in:
Appender, PreparedStatement, Value
Defined in:
lib/duckdb/converter.rb,
lib/duckdb/converter/int_to_sym.rb,
ext/duckdb/conveter.c

Overview

:nodoc: all

Defined Under Namespace

Modules: IntToSym

Constant Summary collapse

RANGE_INT8 =
-128..127
RANGE_INT16 =
-32_768..32_767
RANGE_INT32 =
-2_147_483_648..2_147_483_647
RANGE_INT64 =
-9_223_372_036_854_775_808..9_223_372_036_854_775_807
RANGE_UINT8 =
0..255
RANGE_UINT16 =
0..65_535
RANGE_UINT32 =
0..4_294_967_295
RANGE_UINT64 =
0..18_446_744_073_709_551_615
RANGE_HUGEINT =
(-(1 << 127)..((1 << 127) - 1))
RANGE_UHUGEINT =
(0..((1 << 128) - 1))
HALF_HUGEINT_BIT =
64
HALF_HUGEINT =
1 << HALF_HUGEINT_BIT
LOWER_HUGEINT_MASK =
HALF_HUGEINT - 1
EPOCH =
Time.local(1970, 1, 1)
EPOCH_UTC =
Time.utc(1970, 1, 1)

Class Method Summary collapse

Class Method Details

._decimal_to_unscaled(value, scale) ⇒ Object



134
135
136
# File 'lib/duckdb/converter.rb', line 134

def _decimal_to_unscaled(value, scale)
  (value * (10**scale)).to_i
end

._hugeint_lower(value) ⇒ Object



117
118
119
# File 'lib/duckdb/converter.rb', line 117

def _hugeint_lower(value)
  value & LOWER_HUGEINT_MASK
end

._hugeint_upper(value) ⇒ Object



121
122
123
# File 'lib/duckdb/converter.rb', line 121

def _hugeint_upper(value)
  value >> HALF_HUGEINT_BIT
end

._parse_date(value) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/duckdb/converter.rb', line 142

def _parse_date(value)
  case value
  when Date, Time
    value
  else
    Date.parse(value)
  end
rescue StandardError => e
  raise(ArgumentError, "Cannot parse `#{value.inspect}` to Date object. #{e.message}")
end

._parse_deciaml(value) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/duckdb/converter.rb', line 166

def _parse_deciaml(value)
  case value
  when BigDecimal
    value
  else
    begin
      BigDecimal(value.to_s)
    rescue StandardError => e
      raise(ArgumentError, "Cannot parse `#{value.inspect}` to BigDecimal object. #{e.message}")
    end
  end
end

._parse_time(value) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/duckdb/converter.rb', line 153

def _parse_time(value)
  case value
  when Time
    value
  when DateTime
    value.to_time
  else
    Time.parse(value)
  end
rescue StandardError => e
  raise(ArgumentError, "Cannot parse `#{value.inspect}` to Time object. #{e.message}")
end

._to_date(year, month, day) ⇒ Object



42
43
44
# File 'lib/duckdb/converter.rb', line 42

def _to_date(year, month, day)
  Date.new(year, month, day)
end

._to_decimal_from_hugeint(width, scale, upper, lower = nil) ⇒ Object



125
126
127
128
# File 'lib/duckdb/converter.rb', line 125

def _to_decimal_from_hugeint(width, scale, upper, lower = nil)
  v = lower.nil? ? upper : _to_hugeint_from_vector(lower, upper)
  _to_decimal_from_value(width, scale, v)
end

._to_decimal_from_value(_width, scale, value) ⇒ Object



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

def _to_decimal_from_value(_width, scale, value)
  BigDecimal("#{value}e-#{scale}")
end

._to_hugeint_from_vector(lower, upper) ⇒ Object



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

def _to_hugeint_from_vector(lower, upper)
  (upper << HALF_HUGEINT_BIT) + lower
end

._to_infinity(value) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/duckdb/converter.rb', line 34

def _to_infinity(value)
  if value.positive?
    DuckDB::Infinity::POSITIVE
  else
    DuckDB::Infinity::NEGATIVE
  end
end

._to_interval_from_vector(months, days, micros) ⇒ Object



138
139
140
# File 'lib/duckdb/converter.rb', line 138

def _to_interval_from_vector(months, days, micros)
  Interval.new(interval_months: months, interval_days: days, interval_micros: micros)
end

._to_query_progress(percentage, rows_processed, total_rows_to_process) ⇒ Object



179
180
181
# File 'lib/duckdb/converter.rb', line 179

def _to_query_progress(percentage, rows_processed, total_rows_to_process)
  DuckDB::QueryProgress.new(percentage, rows_processed, total_rows_to_process).freeze
end

._to_time(year, month, day, hour, minute, second, microsecond) ⇒ Object

rubocop:disable Metrics/ParameterLists



47
48
49
50
51
52
# File 'lib/duckdb/converter.rb', line 47

def _to_time(year, month, day, hour, minute, second, microsecond)
  Time.public_send(
    default_timezone_utc? ? :utc : :local,
    year, month, day, hour, minute, second, microsecond
  )
end

._to_time_from_duckdb_time(hour, minute, second, microsecond) ⇒ Object

rubocop:enable Metrics/ParameterLists



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/duckdb/converter.rb', line 55

def _to_time_from_duckdb_time(hour, minute, second, microsecond)
  return Time.utc(1970, 1, 1, hour, minute, second, microsecond) if default_timezone_utc?

  Time.parse(
    format(
      '%<hour>02d:%<minute>02d:%<second>02d.%<microsecond>06d',
      hour: hour,
      minute: minute,
      second: second,
      microsecond: microsecond
    )
  )
end

._to_time_from_duckdb_time_ns(nanos) ⇒ Object



89
90
91
92
93
94
95
96
97
# File 'lib/duckdb/converter.rb', line 89

def _to_time_from_duckdb_time_ns(nanos)
  hour = nanos / 3_600_000_000_000
  nanos %= 3_600_000_000_000
  min = nanos / 60_000_000_000
  nanos %= 60_000_000_000
  sec = nanos / 1_000_000_000
  microsecond = (nanos % 1_000_000_000) / 1_000
  _to_time_from_duckdb_time(hour, min, sec, microsecond)
end

._to_time_from_duckdb_time_tz(hour, min, sec, micro, timezone) ⇒ Object



99
100
101
102
103
104
# File 'lib/duckdb/converter.rb', line 99

def _to_time_from_duckdb_time_tz(hour, min, sec, micro, timezone)
  tz_offset = format_timezone_offset(timezone)
  time_str = format('%<hour>02d:%<min>02d:%<sec>02d.%<micro>06d%<tz>s',
                    hour: hour, min: min, sec: sec, micro: micro, tz: tz_offset)
  Time.parse(time_str)
end

._to_time_from_duckdb_timestamp_ms(time) ⇒ Object



77
78
79
80
81
# File 'lib/duckdb/converter.rb', line 77

def _to_time_from_duckdb_timestamp_ms(time)
  _to_time_from_duckdb_timestamp_s(time / 1000).then do |tm|
    _to_time(tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec, time % 1000 * 1000)
  end
end

._to_time_from_duckdb_timestamp_ns(time) ⇒ Object



83
84
85
86
87
# File 'lib/duckdb/converter.rb', line 83

def _to_time_from_duckdb_timestamp_ns(time)
  _to_time_from_duckdb_timestamp_s(time / 1_000_000_000).then do |tm|
    _to_time(tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec, time % 1_000_000_000 / 1000)
  end
end

._to_time_from_duckdb_timestamp_s(time) ⇒ Object



69
70
71
72
73
74
75
# File 'lib/duckdb/converter.rb', line 69

def _to_time_from_duckdb_timestamp_s(time)
  if default_timezone_utc?
    EPOCH_UTC + time
  else
    EPOCH + time
  end
end

._to_time_from_duckdb_timestamp_tz(bits) ⇒ Object



106
107
108
109
110
111
# File 'lib/duckdb/converter.rb', line 106

def _to_time_from_duckdb_timestamp_tz(bits)
  micro = bits % 1_000_000
  time = EPOCH_UTC + (bits / 1_000_000)
  timestamp_str = format_timestamp_with_micro(time, micro)
  Time.parse(timestamp_str)
end

.decimal_to_hugeint(value) ⇒ Object



208
209
210
211
212
213
# File 'lib/duckdb/converter.rb', line 208

def decimal_to_hugeint(value)
  integer_value = (value * (10**value.scale)).to_i
  integer_to_hugeint(integer_value)
rescue FloatDomainError => e
  raise(ArgumentError, "The argument `#{value.inspect}` must be converted to Integer. #{e.message}")
end

.default_timezone_utc?Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/duckdb/converter.rb', line 30

def default_timezone_utc?
  defined?(DuckDB.default_timezone) && DuckDB.default_timezone == :utc
end

.format_timestamp_with_micro(time, micro) ⇒ Object



191
192
193
194
195
# File 'lib/duckdb/converter.rb', line 191

def format_timestamp_with_micro(time, micro)
  format('%<year>04d-%<mon>02d-%<day>02d %<hour>02d:%<min>02d:%<sec>02d.%<micro>06d +0000',
         year: time.year, mon: time.month, day: time.day,
         hour: time.hour, min: time.min, sec: time.sec, micro: micro)
end

.format_timezone_offset(timezone) ⇒ Object



183
184
185
186
187
188
189
# File 'lib/duckdb/converter.rb', line 183

def format_timezone_offset(timezone)
  sign = timezone.negative? ? '-' : '+'
  offset = timezone.abs
  tzhour = offset / 3600
  tzmin = (offset % 3600) / 60
  format('%<sign>s%<hour>02d:%<min>02d', sign: sign, hour: tzhour, min: tzmin)
end

.integer_to_hugeint(value) ⇒ Object



199
200
201
202
203
204
205
206
# File 'lib/duckdb/converter.rb', line 199

def integer_to_hugeint(value)
  case value
  when Integer
    [_hugeint_lower(value), _hugeint_upper(value)]
  else
    raise(ArgumentError, "The argument `#{value.inspect}` must be Integer.")
  end
end