duckdb 1.0.0.0 → 1.0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ded07680dcaaa7309ed8578e6bd5d0a1e217b0c803f8527679e62e254aaea412
4
- data.tar.gz: d2ff3d9a66b1487d867a95129a5c4fff3b4c01ed90198772d2a62b299c88bfca
3
+ metadata.gz: 2a632e159017449943e06edae0808189967be14845c29b479cb77a0d9e6b9da7
4
+ data.tar.gz: ec7b9c0f6d34aa943436e9525e914759dbd775d8c9a02b1eff991e2a03ade249
5
5
  SHA512:
6
- metadata.gz: 253d068a5c17894a482346897f499e06a79ed9741250367e76d306d3828bfdce385379bd091528ae119fa5b1d0c7a83378cb84043477f1d6d21d86d09c00cd88
7
- data.tar.gz: 2c554bdd675fea28561ed291dc28e5b660ef85a7d737d6cd69450832aa3af6a84eb94ad6a55a922828841ee9c9f802a4f86734692afd35b3a2bde4c2d6edb7e7
6
+ metadata.gz: e50c031a4d9f38a87eb77996c90f90a36c4c5f840694bad4a7ce79dcf3d2e439b30fee8e41a21522285ff7db5293e6fa059186c958f7fbed99089455b4ea04db
7
+ data.tar.gz: 65b7187a73f43b89a8ec8997edcce562af456e3b89f697b4e25c23ae114ed712916643d39c81ef323a1b47b6ac4783e384c53477d177a9d73271859e31c0f970
@@ -15,7 +15,7 @@ jobs:
15
15
  runs-on: macos-latest
16
16
  strategy:
17
17
  matrix:
18
- ruby: ['3.0.7', '3.1.6', '3.2.4', '3.3.2', '3.4.0-preview1', 'head']
18
+ ruby: ['3.0.7', '3.1.6', '3.2.4', '3.3.3', '3.4.0-preview1', 'head']
19
19
  duckdb: ['1.0.0', '0.10.3']
20
20
 
21
21
  steps:
@@ -45,11 +45,23 @@ jobs:
45
45
  cp -rip duckdb-tmp-v$DUCKDB_VERSION/build/release/src/*.dylib duckdb-v$DUCKDB_VERSION/build/release/src
46
46
  cp -rip duckdb-tmp-v$DUCKDB_VERSION/src/include duckdb-v$DUCKDB_VERSION/src/
47
47
 
48
- - name: Build with Ruby ${{ matrix.ruby }}
48
+ - name: bundle install with Ruby ${{ matrix.ruby }}
49
49
  env:
50
50
  DUCKDB_VERSION: ${{ matrix.duckdb }}
51
51
  run: |
52
52
  bundle install --jobs 4 --retry 3
53
+
54
+ - name: Build test with DUCKDB_API_NO_DEPRECATED and Ruby ${{ matrix.ruby }}
55
+ env:
56
+ DUCKDB_VERSION: ${{ matrix.duckdb }}
57
+ run: |
58
+ env DUCKDB_API_NO_DEPRECATED=1 bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/src/include --with-duckdb-lib=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/build/release/src/
59
+ bundle exec rake clean
60
+
61
+ - name: Build with Ruby ${{ matrix.ruby }}
62
+ env:
63
+ DUCKDB_VERSION: ${{ matrix.duckdb }}
64
+ run: |
53
65
  bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/src/include --with-duckdb-lib=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/build/release/src/
54
66
 
55
67
  - name: test with Ruby ${{ matrix.ruby }}
@@ -15,7 +15,7 @@ jobs:
15
15
  runs-on: ubuntu-latest
16
16
  strategy:
17
17
  matrix:
18
- ruby: ['3.0.7', '3.1.6', '3.2.4', '3.3.2', '3.4.0-preview1', 'head']
18
+ ruby: ['3.0.7', '3.1.6', '3.2.4', '3.3.3', '3.4.0-preview1', 'head']
19
19
  duckdb: ['1.0.0', '0.10.3']
20
20
 
21
21
  steps:
@@ -45,11 +45,23 @@ jobs:
45
45
  cp -rip duckdb-tmp-v$DUCKDB_VERSION/build/release/src/*.so duckdb-v$DUCKDB_VERSION/build/release/src
46
46
  cp -rip duckdb-tmp-v$DUCKDB_VERSION/src/include duckdb-v$DUCKDB_VERSION/src/
47
47
 
48
- - name: Build with Ruby ${{ matrix.ruby }}
48
+ - name: bundle install with Ruby ${{ matrix.ruby }}
49
49
  env:
50
50
  DUCKDB_VERSION: ${{ matrix.duckdb }}
51
51
  run: |
52
52
  bundle install --jobs 4 --retry 3
53
+
54
+ - name: Build test with DUCKDB_API_NO_DEPRECATED and Ruby ${{ matrix.ruby }}
55
+ env:
56
+ DUCKDB_VERSION: ${{ matrix.duckdb }}
57
+ run: |
58
+ env DUCKDB_API_NO_DEPRECATED=1 bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/src/include --with-duckdb-lib=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/build/release/src/
59
+ bundle exec rake clean
60
+
61
+ - name: Build with Ruby ${{ matrix.ruby }}
62
+ env:
63
+ DUCKDB_VERSION: ${{ matrix.duckdb }}
64
+ run: |
53
65
  bundle exec rake build -- --with-duckdb-include=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/src/include --with-duckdb-lib=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/build/release/src/
54
66
 
55
67
  - name: test with Ruby ${{ matrix.ruby }}
@@ -15,7 +15,7 @@ jobs:
15
15
  runs-on: windows-latest
16
16
  strategy:
17
17
  matrix:
18
- ruby: ['3.0.7', '3.1.5', '3.2.4', '3.3.1', 'ucrt', 'mingw', 'mswin', 'head']
18
+ ruby: ['3.0.7', '3.1.5', '3.2.4', '3.3.2', 'ucrt', 'mingw', 'mswin', 'head']
19
19
  duckdb: ['1.0.0', '0.10.3']
20
20
 
21
21
  steps:
data/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ # 1.0.0.2 - 2024-06-23
8
+ - DuckDB::Result supports TIMESTAMPTZ column type (only when DuckDB::Result.use_chunk_each is true).
9
+ - Supporting TIMESTAMPTZ is experimental.
10
+ - DuckDB::Result supports TIMETZ column type (only when DuckDB::Result.use_chunk_each is true).
11
+ - DuckDB::Result supports TIMESTAMP_NS column type (only when DuckDB::Result.use_chunk_each is true).
12
+ - DuckDB::Result supports TIMESTAMP_MS column type (only when DuckDB::Result.use_chunk_each is true).
13
+ - DuckDB::Result supports TIMESTAMP_S column type (only when DuckDB::Result.use_chunk_each is true).
14
+ - DuckDB::Result supports STRUCT column type (only when DuckDB::Result.use_chunk_each is true).
15
+ - DuckDB::Result supports MAP column type (only when DuckDB::Result.use_chunk_each is true).
16
+ - DuckDB::Result supports UNION column type (only when DuckDB::Result.use_chunk_each is true).
17
+ - DuckDB::Result supports BIT column type (only when DuckDB::Result.use_chunk_each is true).
18
+
19
+ # 1.0.0.1 - 2024-06-16
20
+ - support fetch the value from UHUGEINT type column.
21
+ - add `DuckDB::Appender#append_uhugeint`.
22
+ - DuckDB::Result supports ARRAY column type (only when DuckDB::Result.use_chunk_each is true).
23
+ - DuckDB::Result supports LIST column type (only when DuckDB::Result.use_chunk_each is true).
24
+ Thanks to stephenprater.
25
+
7
26
  # 1.0.0.0 - 2024-06-08
8
27
  - bump duckdb to 1.0.0.
9
28
  - add `DuckDB::ExtractedStatements` class.
data/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- ARG RUBY_VERSION=3.3.2
1
+ ARG RUBY_VERSION=3.3.3
2
2
  FROM ruby:${RUBY_VERSION}
3
3
 
4
4
  ARG DUCKDB_VERSION=1.0.0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- duckdb (1.0.0.0)
4
+ duckdb (1.0.0.2)
5
5
  bigdecimal (>= 3.1.4)
6
6
 
7
7
  GEM
@@ -10,11 +10,11 @@ GEM
10
10
  benchmark-ips (2.13.0)
11
11
  bigdecimal (3.1.8)
12
12
  mini_portile2 (2.8.7)
13
- minitest (5.23.1)
14
- nokogiri (1.16.5)
13
+ minitest (5.24.0)
14
+ nokogiri (1.16.6)
15
15
  mini_portile2 (~> 2.8.2)
16
16
  racc (~> 1.4)
17
- nokogiri (1.16.5-x86_64-linux)
17
+ nokogiri (1.16.6-x86_64-linux)
18
18
  racc (~> 1.4)
19
19
  racc (1.8.0)
20
20
  rake (13.2.1)
@@ -28,6 +28,7 @@ static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VAL
28
28
  static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec, VALUE micros);
29
29
  static VALUE appender__append_timestamp(VALUE self, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
30
30
  static VALUE appender__append_hugeint(VALUE self, VALUE lower, VALUE upper);
31
+ static VALUE appender__append_uhugeint(VALUE self, VALUE lower, VALUE upper);
31
32
  static VALUE appender_flush(VALUE self);
32
33
  static VALUE appender_close(VALUE self);
33
34
 
@@ -349,6 +350,21 @@ static VALUE appender__append_hugeint(VALUE self, VALUE lower, VALUE upper) {
349
350
  return self;
350
351
  }
351
352
 
353
+ static VALUE appender__append_uhugeint(VALUE self, VALUE lower, VALUE upper) {
354
+ duckdb_uhugeint uhugeint;
355
+
356
+ uhugeint.lower = NUM2ULL(lower);
357
+ uhugeint.upper = NUM2ULL(upper);
358
+
359
+ rubyDuckDBAppender *ctx;
360
+
361
+ TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
362
+ if (duckdb_append_uhugeint(ctx->appender, uhugeint) == DuckDBError) {
363
+ rb_raise(eDuckDBError, "failed to append uhugeint");
364
+ }
365
+ return self;
366
+ }
367
+
352
368
  static VALUE appender_flush(VALUE self) {
353
369
  rubyDuckDBAppender *ctx;
354
370
  TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
@@ -395,6 +411,7 @@ void rbduckdb_init_duckdb_appender(void) {
395
411
  rb_define_private_method(cDuckDBAppender, "_append_time", appender__append_time, 4);
396
412
  rb_define_private_method(cDuckDBAppender, "_append_timestamp", appender__append_timestamp, 7);
397
413
  rb_define_private_method(cDuckDBAppender, "_append_hugeint", appender__append_hugeint, 2);
414
+ rb_define_private_method(cDuckDBAppender, "_append_uhugeint", appender__append_uhugeint, 2);
398
415
  rb_define_method(cDuckDBAppender, "flush", appender_flush, 0);
399
416
  rb_define_method(cDuckDBAppender, "close", appender_close, 0);
400
417
  }
@@ -70,4 +70,6 @@ have_func('duckdb_fetch_chunk', 'duckdb.h')
70
70
  # duckdb_parameter_name in duckdb <= 0.9.1 is not found on Windows.
71
71
  have_func('duckdb_parameter_name', 'duckdb.h')
72
72
 
73
+ $CFLAGS << ' -DDUCKDB_API_NO_DEPRECATED' if ENV['DUCKDB_API_NO_DEPRECATED']
74
+
73
75
  create_makefile('duckdb/duckdb_native')
data/ext/duckdb/result.c CHANGED
@@ -13,6 +13,11 @@ static ID id__to_interval_from_vector;
13
13
  static ID id__to_hugeint_from_vector;
14
14
  static ID id__to_decimal_from_hugeint;
15
15
  static ID id__to_uuid_from_vector;
16
+ static ID id__to_time_from_duckdb_timestamp_s;
17
+ static ID id__to_time_from_duckdb_timestamp_ms;
18
+ static ID id__to_time_from_duckdb_timestamp_ns;
19
+ static ID id__to_time_from_duckdb_time_tz;
20
+ static ID id__to_time_from_duckdb_timestamp_tz;
16
21
 
17
22
  static void deallocate(void *ctx);
18
23
  static VALUE allocate(VALUE klass);
@@ -62,11 +67,21 @@ static VALUE vector_interval(void* vector_data, idx_t row_idx);
62
67
  static VALUE vector_blob(void* vector_data, idx_t row_idx);
63
68
  static VALUE vector_varchar(void* vector_data, idx_t row_idx);
64
69
  static VALUE vector_hugeint(void* vector_data, idx_t row_idx);
70
+ static VALUE vector_uhugeint(void* vector_data, idx_t row_idx);
65
71
  static VALUE vector_decimal(duckdb_logical_type ty, void* vector_data, idx_t row_idx);
72
+ static VALUE vector_timestamp_s(void* vector_data, idx_t row_idx);
73
+ static VALUE vector_timestamp_ms(void* vector_data, idx_t row_idx);
74
+ static VALUE vector_timestamp_ns(void* vector_data, idx_t row_idx);
66
75
  static VALUE vector_enum(duckdb_logical_type ty, void* vector_data, idx_t row_idx);
67
- static VALUE vector_list(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx);
68
- static VALUE vector_map(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx);
76
+ static VALUE vector_array(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx);
77
+ static VALUE vector_value_at(duckdb_vector vector, duckdb_logical_type element_type, idx_t index);
78
+ static VALUE vector_list(duckdb_logical_type ty, duckdb_vector vector, void* vector_data, idx_t row_idx);
79
+ static VALUE vector_map(duckdb_logical_type ty, duckdb_vector vector, void* vector_data, idx_t row_idx);
69
80
  static VALUE vector_struct(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx);
81
+ static VALUE vector_union(duckdb_logical_type ty, duckdb_vector vector, void* vector_data, idx_t row_idx);
82
+ static VALUE vector_bit(void* vector_data, idx_t row_idx);
83
+ static VALUE vector_time_tz(void* vector_data, idx_t row_idx);
84
+ static VALUE vector_timestamp_tz(void* vector_data, idx_t row_idx);
70
85
  static VALUE vector_uuid(void* vector_data, idx_t row_idx);
71
86
  static VALUE vector_value(duckdb_vector vector, idx_t row_idx);
72
87
 
@@ -662,6 +677,14 @@ static VALUE vector_hugeint(void* vector_data, idx_t row_idx) {
662
677
  );
663
678
  }
664
679
 
680
+ static VALUE vector_uhugeint(void* vector_data, idx_t row_idx) {
681
+ duckdb_uhugeint uhugeint = ((duckdb_uhugeint *)vector_data)[row_idx];
682
+ return rb_funcall(mDuckDBConverter, id__to_hugeint_from_vector, 2,
683
+ ULL2NUM(uhugeint.lower),
684
+ ULL2NUM(uhugeint.upper)
685
+ );
686
+ }
687
+
665
688
  static VALUE vector_decimal(duckdb_logical_type ty, void* vector_data, idx_t row_idx) {
666
689
  VALUE width = INT2FIX(duckdb_decimal_width(ty));
667
690
  VALUE scale = INT2FIX(duckdb_decimal_scale(ty));
@@ -700,6 +723,27 @@ static VALUE vector_decimal(duckdb_logical_type ty, void* vector_data, idx_t row
700
723
  );
701
724
  }
702
725
 
726
+ static VALUE vector_timestamp_s(void* vector_data, idx_t row_idx) {
727
+ duckdb_timestamp data = ((duckdb_timestamp *)vector_data)[row_idx];
728
+ return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_s, 1,
729
+ LL2NUM(data.micros)
730
+ );
731
+ }
732
+
733
+ static VALUE vector_timestamp_ms(void* vector_data, idx_t row_idx) {
734
+ duckdb_timestamp data = ((duckdb_timestamp *)vector_data)[row_idx];
735
+ return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_ms, 1,
736
+ LL2NUM(data.micros)
737
+ );
738
+ }
739
+
740
+ static VALUE vector_timestamp_ns(void* vector_data, idx_t row_idx) {
741
+ duckdb_timestamp data = ((duckdb_timestamp *)vector_data)[row_idx];
742
+ return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_ns, 1,
743
+ LL2NUM(data.micros)
744
+ );
745
+ }
746
+
703
747
  static VALUE vector_enum(duckdb_logical_type ty, void* vector_data, idx_t row_idx) {
704
748
  duckdb_type type = duckdb_enum_internal_type(ty);
705
749
  uint8_t index;
@@ -721,97 +765,38 @@ static VALUE vector_enum(duckdb_logical_type ty, void* vector_data, idx_t row_id
721
765
  return value;
722
766
  }
723
767
 
724
- static VALUE vector_list(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx) {
725
- // Lists are stored as vectors within vectors
726
-
768
+ static VALUE vector_array(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx) {
727
769
  VALUE ary = Qnil;
728
- VALUE element = Qnil;
729
- idx_t i;
730
-
731
- // rb_warn("ruby-duckdb does not support List yet");
732
-
733
- duckdb_logical_type child_logical_type = duckdb_list_type_child_type(ty);
734
- // duckdb_type child_type = duckdb_get_type_id(child_logical_type);
735
-
736
- duckdb_list_entry list_entry = ((duckdb_list_entry *)vector)[row_idx];
737
- ary = rb_ary_new2(list_entry.length);
738
-
739
- for (i = list_entry.offset; i < list_entry.offset + list_entry.length; ++i) {
740
- /*
741
- * FIXME: How to get the child element?
742
- */
743
- // element = ???
744
- rb_ary_store(ary, i - list_entry.offset, element);
745
- }
746
- duckdb_destroy_logical_type(&child_logical_type);
747
- return ary;
748
- }
749
-
750
- static VALUE vector_map(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx) {
751
- VALUE hash = rb_hash_new();
752
-
753
- duckdb_logical_type key_logical_type = duckdb_map_type_key_type(ty);
754
- duckdb_logical_type value_logical_type = duckdb_map_type_value_type(ty);
755
- // duckdb_type key_type = duckdb_get_type_id(key_logical_type);
756
- // duckdb_type value_type = duckdb_get_type_id(value_logical_type);
757
-
758
- /*
759
- * FIXME: How to get key and value?
760
- *
761
- * rb_hash_aset(hash, key, value);
762
- */
763
- duckdb_destroy_logical_type(&key_logical_type);
764
- duckdb_destroy_logical_type(&value_logical_type);
765
- return hash;
766
- }
767
-
768
- static VALUE vector_struct(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx) {
769
- VALUE hash = rb_hash_new();
770
770
  VALUE value = Qnil;
771
- VALUE key = Qnil;
772
- char *p;
773
771
 
774
- idx_t child_count = duckdb_struct_type_child_count(ty);
772
+ duckdb_logical_type child_logical_type = duckdb_array_type_child_type(ty);
773
+ idx_t size = duckdb_array_type_array_size(ty);
774
+ idx_t bgn = row_idx * size;
775
+ idx_t end = bgn + size;
776
+ duckdb_vector child = duckdb_array_vector_get_child(vector);
775
777
 
776
- for (idx_t i = 0; i < child_count; ++i) {
777
- p = duckdb_struct_type_child_name(ty, i);
778
- if (p) {
779
- key = rb_str_new2(p);
780
- // FIXME
781
- // How to get Struct values?
782
- // value = ???
783
- // duckdb_vector child_vector = duckdb_struct_vector_get_child(vector, i);
784
- // VALUE value = vector_value(child_vector, i);
785
- rb_hash_aset(hash, key, value);
786
- duckdb_free(p);
787
- }
778
+ ary = rb_ary_new2(size);
779
+ for (idx_t i = bgn; i < end; ++i) {
780
+ value = vector_value_at(child, child_logical_type, i);
781
+ rb_ary_store(ary, i - bgn, value);
788
782
  }
789
783
 
790
- return hash;
791
- }
792
-
793
- static VALUE vector_uuid(void* vector_data, idx_t row_idx) {
794
- duckdb_hugeint hugeint = ((duckdb_hugeint *)vector_data)[row_idx];
795
- return rb_funcall(mDuckDBConverter, id__to_uuid_from_vector, 2,
796
- ULL2NUM(hugeint.lower),
797
- LL2NUM(hugeint.upper)
798
- );
784
+ duckdb_destroy_logical_type(&child_logical_type);
785
+ return ary;
799
786
  }
800
787
 
801
- static VALUE vector_value(duckdb_vector vector, idx_t row_idx) {
788
+ static VALUE vector_value_at(duckdb_vector vector, duckdb_logical_type element_type, idx_t index) {
802
789
  uint64_t *validity;
803
- duckdb_logical_type ty;
804
790
  duckdb_type type_id;
805
791
  void* vector_data;
806
792
  VALUE obj = Qnil;
807
793
 
808
794
  validity = duckdb_vector_get_validity(vector);
809
- if (!duckdb_validity_row_is_valid(validity, row_idx)) {
795
+ if (!duckdb_validity_row_is_valid(validity, index)) {
810
796
  return Qnil;
811
797
  }
812
798
 
813
- ty = duckdb_vector_get_column_type(vector);
814
- type_id = duckdb_get_type_id(ty);
799
+ type_id = duckdb_get_type_id(element_type);
815
800
  vector_data = duckdb_vector_get_data(vector);
816
801
 
817
802
  switch(type_id) {
@@ -819,82 +804,283 @@ static VALUE vector_value(duckdb_vector vector, idx_t row_idx) {
819
804
  obj = Qnil;
820
805
  break;
821
806
  case DUCKDB_TYPE_BOOLEAN:
822
- obj = (((bool*) vector_data)[row_idx]) ? Qtrue : Qfalse;
807
+ obj = (((bool*) vector_data)[index]) ? Qtrue : Qfalse;
823
808
  break;
824
809
  case DUCKDB_TYPE_TINYINT:
825
- obj = INT2FIX(((int8_t *) vector_data)[row_idx]);
810
+ obj = INT2FIX(((int8_t *) vector_data)[index]);
826
811
  break;
827
812
  case DUCKDB_TYPE_SMALLINT:
828
- obj = INT2FIX(((int16_t *) vector_data)[row_idx]);
813
+ obj = INT2FIX(((int16_t *) vector_data)[index]);
829
814
  break;
830
815
  case DUCKDB_TYPE_INTEGER:
831
- obj = INT2NUM(((int32_t *) vector_data)[row_idx]);
816
+ obj = INT2NUM(((int32_t *) vector_data)[index]);
832
817
  break;
833
818
  case DUCKDB_TYPE_BIGINT:
834
- obj = LL2NUM(((int64_t *) vector_data)[row_idx]);
819
+ obj = LL2NUM(((int64_t *) vector_data)[index]);
835
820
  break;
836
821
  case DUCKDB_TYPE_UTINYINT:
837
- obj = INT2FIX(((uint8_t *) vector_data)[row_idx]);
822
+ obj = INT2FIX(((uint8_t *) vector_data)[index]);
838
823
  break;
839
824
  case DUCKDB_TYPE_USMALLINT:
840
- obj = INT2FIX(((uint16_t *) vector_data)[row_idx]);
825
+ obj = INT2FIX(((uint16_t *) vector_data)[index]);
841
826
  break;
842
827
  case DUCKDB_TYPE_UINTEGER:
843
- obj = UINT2NUM(((uint32_t *) vector_data)[row_idx]);
828
+ obj = UINT2NUM(((uint32_t *) vector_data)[index]);
844
829
  break;
845
830
  case DUCKDB_TYPE_UBIGINT:
846
- obj = ULL2NUM(((uint64_t *) vector_data)[row_idx]);
847
- break;
848
- case DUCKDB_TYPE_HUGEINT:
849
- obj = vector_hugeint(vector_data, row_idx);
831
+ obj = ULL2NUM(((uint64_t *) vector_data)[index]);
850
832
  break;
851
833
  case DUCKDB_TYPE_FLOAT:
852
- obj = DBL2NUM((((float *) vector_data)[row_idx]));
834
+ obj = DBL2NUM((((float *) vector_data)[index]));
853
835
  break;
854
836
  case DUCKDB_TYPE_DOUBLE:
855
- obj = DBL2NUM((((double *) vector_data)[row_idx]));
856
- break;
857
- case DUCKDB_TYPE_DATE:
858
- obj = vector_date(vector_data, row_idx);
837
+ obj = DBL2NUM((((double *) vector_data)[index]));
859
838
  break;
860
839
  case DUCKDB_TYPE_TIMESTAMP:
861
- obj = vector_timestamp(vector_data, row_idx);
840
+ obj = vector_timestamp(vector_data, index);
841
+ break;
842
+ case DUCKDB_TYPE_DATE:
843
+ obj = vector_date(vector_data, index);
862
844
  break;
863
845
  case DUCKDB_TYPE_TIME:
864
- obj = vector_time(vector_data, row_idx);
846
+ obj = vector_time(vector_data, index);
865
847
  break;
866
848
  case DUCKDB_TYPE_INTERVAL:
867
- obj = vector_interval(vector_data, row_idx);
849
+ obj = vector_interval(vector_data, index);
850
+ break;
851
+ case DUCKDB_TYPE_HUGEINT:
852
+ obj = vector_hugeint(vector_data, index);
853
+ break;
854
+ case DUCKDB_TYPE_UHUGEINT:
855
+ obj = vector_uhugeint(vector_data, index);
868
856
  break;
869
857
  case DUCKDB_TYPE_VARCHAR:
870
- obj = vector_varchar(vector_data, row_idx);
858
+ obj = vector_varchar(vector_data, index);
871
859
  break;
872
860
  case DUCKDB_TYPE_BLOB:
873
- obj = vector_blob(vector_data, row_idx);
861
+ obj = vector_blob(vector_data, index);
874
862
  break;
875
863
  case DUCKDB_TYPE_DECIMAL:
876
- obj = vector_decimal(ty, vector_data, row_idx);
864
+ obj = vector_decimal(element_type, vector_data, index);
865
+ break;
866
+ case DUCKDB_TYPE_TIMESTAMP_S:
867
+ obj = vector_timestamp_s(vector_data, index);
868
+ break;
869
+ case DUCKDB_TYPE_TIMESTAMP_MS:
870
+ obj = vector_timestamp_ms(vector_data, index);
871
+ break;
872
+ case DUCKDB_TYPE_TIMESTAMP_NS:
873
+ obj = vector_timestamp_ns(vector_data, index);
877
874
  break;
878
875
  case DUCKDB_TYPE_ENUM:
879
- obj = vector_enum(ty, vector_data, row_idx);
876
+ obj = vector_enum(element_type, vector_data, index);
880
877
  break;
881
878
  case DUCKDB_TYPE_LIST:
882
- obj = vector_list(ty, vector_data, row_idx);
879
+ obj = vector_list(element_type, vector, vector_data, index);
880
+ break;
881
+ case DUCKDB_TYPE_STRUCT:
882
+ obj = vector_struct(element_type, vector, index);
883
883
  break;
884
884
  case DUCKDB_TYPE_MAP:
885
- obj = vector_map(ty, vector_data, row_idx);
885
+ obj = vector_map(element_type, vector, vector_data, index);
886
886
  break;
887
- case DUCKDB_TYPE_STRUCT:
888
- obj = vector_struct(ty, vector_data, row_idx);
887
+ case DUCKDB_TYPE_ARRAY:
888
+ obj = vector_array(element_type, vector, index);
889
889
  break;
890
890
  case DUCKDB_TYPE_UUID:
891
- obj = vector_uuid(vector_data, row_idx);
891
+ obj = vector_uuid(vector_data, index);
892
+ break;
893
+ case DUCKDB_TYPE_UNION:
894
+ obj = vector_union(element_type, vector, vector_data, index);
895
+ break;
896
+ case DUCKDB_TYPE_BIT:
897
+ obj = vector_bit(vector_data, index);
898
+ break;
899
+ case DUCKDB_TYPE_TIME_TZ:
900
+ obj = vector_time_tz(vector_data, index);
901
+ break;
902
+ case DUCKDB_TYPE_TIMESTAMP_TZ:
903
+ obj = vector_timestamp_tz(vector_data, index);
892
904
  break;
893
905
  default:
894
906
  rb_warn("Unknown type %d", type_id);
895
907
  obj = Qnil;
896
908
  }
897
909
 
910
+ return obj;
911
+ }
912
+
913
+ static VALUE vector_list(duckdb_logical_type ty, duckdb_vector vector, void * vector_data, idx_t row_idx) {
914
+ VALUE ary = Qnil;
915
+ VALUE value = Qnil;
916
+ idx_t i;
917
+
918
+ duckdb_logical_type child_logical_type = duckdb_list_type_child_type(ty);
919
+
920
+ duckdb_list_entry list_entry = ((duckdb_list_entry *)vector_data)[row_idx];
921
+ idx_t bgn = list_entry.offset;
922
+ idx_t end = bgn + list_entry.length;
923
+ ary = rb_ary_new2(list_entry.length);
924
+
925
+ duckdb_vector child = duckdb_list_vector_get_child(vector);
926
+
927
+ for (i = bgn; i < end; ++i) {
928
+ value = vector_value_at(child, child_logical_type, i);
929
+ rb_ary_store(ary, i - bgn, value);
930
+ }
931
+ duckdb_destroy_logical_type(&child_logical_type);
932
+ return ary;
933
+ }
934
+
935
+ static VALUE vector_map(duckdb_logical_type ty, duckdb_vector vector, void* vector_data, idx_t row_idx) {
936
+ VALUE hash = rb_hash_new();
937
+ VALUE key = Qnil;
938
+ VALUE value = Qnil;
939
+
940
+ duckdb_logical_type key_logical_type = duckdb_map_type_key_type(ty);
941
+ duckdb_logical_type value_logical_type = duckdb_map_type_value_type(ty);
942
+
943
+ duckdb_list_entry list_entry = ((duckdb_list_entry *)vector_data)[row_idx];
944
+
945
+ idx_t bgn = list_entry.offset;
946
+ idx_t end = bgn + list_entry.length;
947
+
948
+ duckdb_vector child = duckdb_list_vector_get_child(vector);
949
+ duckdb_vector key_vector = duckdb_struct_vector_get_child(child, 0);
950
+ duckdb_vector value_vector = duckdb_struct_vector_get_child(child, 1);
951
+
952
+ for (idx_t i = bgn; i < end; ++i) {
953
+ key = vector_value_at(key_vector, key_logical_type, i);
954
+ value = vector_value_at(value_vector, value_logical_type, i);
955
+ rb_hash_aset(hash, key, value);
956
+ }
957
+
958
+ duckdb_destroy_logical_type(&key_logical_type);
959
+ duckdb_destroy_logical_type(&value_logical_type);
960
+ return hash;
961
+ }
962
+
963
+ static VALUE vector_struct(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx) {
964
+ VALUE hash = rb_hash_new();
965
+ VALUE value = Qnil;
966
+ VALUE key = Qnil;
967
+ duckdb_vector child;
968
+ duckdb_logical_type child_type;
969
+ char *p;
970
+
971
+ idx_t child_count = duckdb_struct_type_child_count(ty);
972
+
973
+ for (idx_t i = 0; i < child_count; ++i) {
974
+ p = duckdb_struct_type_child_name(ty, i);
975
+ if (p) {
976
+ key = ID2SYM(rb_intern_const(p));
977
+ child = duckdb_struct_vector_get_child(vector, i);
978
+ child_type = duckdb_struct_type_child_type(ty, i);
979
+ value = vector_value_at(child, child_type, row_idx);
980
+ rb_hash_aset(hash, key, value);
981
+ duckdb_destroy_logical_type(&child_type);
982
+ duckdb_free(p);
983
+ }
984
+ }
985
+
986
+ return hash;
987
+ }
988
+
989
+ static VALUE vector_union(duckdb_logical_type ty, duckdb_vector vector, void* vector_data, idx_t row_idx){
990
+ VALUE value = Qnil;
991
+ duckdb_vector type_vector = duckdb_struct_vector_get_child(vector, 0);
992
+ void *data = duckdb_vector_get_data(type_vector);
993
+ uint8_t index = ((int8_t *)data)[row_idx];
994
+
995
+ duckdb_logical_type child_type = duckdb_union_type_member_type(ty, index);
996
+
997
+ duckdb_vector vector_value = duckdb_struct_vector_get_child(vector, index + 1);
998
+ value = vector_value_at(vector_value, child_type, row_idx);
999
+ duckdb_destroy_logical_type(&child_type);
1000
+ return value;
1001
+ }
1002
+
1003
+ static VALUE str_concat_byte(VALUE str, unsigned char byte, int offset) {
1004
+ char x[8];
1005
+ char *p = x;
1006
+ for (int j = 7; j >=0; j--) {
1007
+ if (byte % 2 == 1) {
1008
+ x[j] = '1';
1009
+ } else {
1010
+ x[j] = '0';
1011
+ }
1012
+ byte = (byte >> 1);
1013
+ }
1014
+ if (offset > 0 && offset < 8) {
1015
+ p = x + offset;
1016
+ }
1017
+ return rb_str_cat(str, p, 8 - offset);
1018
+ }
1019
+
1020
+ static VALUE bytes_to_string(char *bytes, uint32_t length, int offset) {
1021
+ VALUE str = rb_str_new_literal("");
1022
+ str = str_concat_byte(str, bytes[0], offset);
1023
+ for (uint32_t i = 1; i < length; i++) {
1024
+ str = str_concat_byte(str, bytes[i], 0);
1025
+ }
1026
+ return str;
1027
+ }
1028
+
1029
+ static VALUE vector_bit(void* vector_data, idx_t row_idx) {
1030
+ duckdb_string_t s = (((duckdb_string_t *)vector_data)[row_idx]);
1031
+ char *p;
1032
+ int offset;
1033
+ uint32_t length;
1034
+ VALUE str = Qnil;
1035
+
1036
+ if(duckdb_string_is_inlined(s)) {
1037
+ length = s.value.inlined.length - 1;
1038
+ p = &s.value.inlined.inlined[1];
1039
+ offset = s.value.inlined.inlined[0];
1040
+ str = bytes_to_string(p, length, offset);
1041
+ } else {
1042
+ length = s.value.pointer.length - 1;
1043
+ p = &s.value.pointer.ptr[1];
1044
+ offset = s.value.pointer.ptr[0];
1045
+ str = bytes_to_string(p, length, offset);
1046
+ }
1047
+ return str;
1048
+ }
1049
+
1050
+ static VALUE vector_time_tz(void* vector_data, idx_t row_idx) {
1051
+ duckdb_time_tz_struct data = duckdb_from_time_tz(((duckdb_time_tz *)vector_data)[row_idx]);
1052
+ return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_time_tz, 5,
1053
+ INT2FIX(data.time.hour),
1054
+ INT2FIX(data.time.min),
1055
+ INT2FIX(data.time.sec),
1056
+ INT2NUM(data.time.micros),
1057
+ INT2NUM(data.offset)
1058
+ );
1059
+ }
1060
+
1061
+ static VALUE vector_timestamp_tz(void* vector_data, idx_t row_idx) {
1062
+ duckdb_time_tz data = ((duckdb_time_tz *)vector_data)[row_idx];
1063
+ return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_tz, 1,
1064
+ ULL2NUM(data.bits)
1065
+ );
1066
+ }
1067
+
1068
+ static VALUE vector_uuid(void* vector_data, idx_t row_idx) {
1069
+ duckdb_hugeint hugeint = ((duckdb_hugeint *)vector_data)[row_idx];
1070
+ return rb_funcall(mDuckDBConverter, id__to_uuid_from_vector, 2,
1071
+ ULL2NUM(hugeint.lower),
1072
+ LL2NUM(hugeint.upper)
1073
+ );
1074
+ }
1075
+
1076
+ static VALUE vector_value(duckdb_vector vector, idx_t row_idx) {
1077
+ duckdb_logical_type ty;
1078
+ VALUE obj = Qnil;
1079
+
1080
+ ty = duckdb_vector_get_column_type(vector);
1081
+
1082
+ obj = vector_value_at(vector, ty, row_idx);
1083
+
898
1084
  duckdb_destroy_logical_type(&ty);
899
1085
  return obj;
900
1086
  }
@@ -908,6 +1094,11 @@ void rbduckdb_init_duckdb_result(void) {
908
1094
  id__to_hugeint_from_vector = rb_intern("_to_hugeint_from_vector");
909
1095
  id__to_decimal_from_hugeint = rb_intern("_to_decimal_from_hugeint");
910
1096
  id__to_uuid_from_vector = rb_intern("_to_uuid_from_vector");
1097
+ id__to_time_from_duckdb_timestamp_s = rb_intern("_to_time_from_duckdb_timestamp_s");
1098
+ id__to_time_from_duckdb_timestamp_ms = rb_intern("_to_time_from_duckdb_timestamp_ms");
1099
+ id__to_time_from_duckdb_timestamp_ns = rb_intern("_to_time_from_duckdb_timestamp_ns");
1100
+ id__to_time_from_duckdb_time_tz = rb_intern("_to_time_from_duckdb_time_tz");
1101
+ id__to_time_from_duckdb_timestamp_tz = rb_intern("_to_time_from_duckdb_timestamp_tz");
911
1102
 
912
1103
  rb_define_alloc_func(cDuckDBResult, allocate);
913
1104
 
@@ -39,6 +39,24 @@ module DuckDB
39
39
  _append_hugeint(lower, upper)
40
40
  end
41
41
 
42
+ #
43
+ # appends unsigned huge int value.
44
+ #
45
+ # require 'duckdb'
46
+ # db = DuckDB::Database.open
47
+ # con = db.connect
48
+ # con.query('CREATE TABLE numbers (num UHUGEINT)')
49
+ # appender = con.appender('numbers')
50
+ # appender
51
+ # .begin_row
52
+ # .append_hugeint(340_282_366_920_938_463_463_374_607_431_768_211_455)
53
+ # .end_row
54
+ #
55
+ def append_uhugeint(value)
56
+ lower, upper = integer_to_hugeint(value)
57
+ _append_uhugeint(lower, upper)
58
+ end
59
+
42
60
  #
43
61
  # appends date value.
44
62
  #
@@ -10,6 +10,8 @@ module DuckDB
10
10
  HALF_HUGEINT_BIT = 64
11
11
  HALF_HUGEINT = 1 << HALF_HUGEINT_BIT
12
12
  FLIP_HUGEINT = 1 << 63
13
+ EPOCH = Time.local(1970, 1, 1)
14
+ EPOCH_UTC = Time.new(1970, 1, 1, 0, 0, 0, 0)
13
15
 
14
16
  module_function
15
17
 
@@ -33,6 +35,63 @@ module DuckDB
33
35
  )
34
36
  end
35
37
 
38
+ def _to_time_from_duckdb_timestamp_s(time)
39
+ EPOCH + time
40
+ end
41
+
42
+ def _to_time_from_duckdb_timestamp_ms(time)
43
+ tm = EPOCH + (time / 1000)
44
+ Time.local(tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec, time % 1000 * 1000)
45
+ end
46
+
47
+ def _to_time_from_duckdb_timestamp_ns(time)
48
+ tm = EPOCH + (time / 1_000_000_000)
49
+ Time.local(tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec, time % 1_000_000_000 / 1000)
50
+ end
51
+
52
+ def _to_time_from_duckdb_time_tz(hour, min, sec, micro, timezone)
53
+ sign = '+'
54
+ if timezone.negative?
55
+ timezone = -timezone
56
+ sign = '-'
57
+ end
58
+
59
+ tzhour = timezone / 3600
60
+ tzmin = (timezone % 3600) / 60
61
+
62
+ Time.parse(
63
+ format(
64
+ '%<hour>02d:%<min>02d:%<sec>02d.%<micro>06d%<sign>s%<tzhour>02d:%<tzmin>02d',
65
+ hour: hour,
66
+ min: min,
67
+ sec: sec,
68
+ micro: micro,
69
+ sign: sign,
70
+ tzhour: tzhour,
71
+ tzmin: tzmin
72
+ )
73
+ )
74
+ end
75
+
76
+ def _to_time_from_duckdb_timestamp_tz(bits)
77
+ micro = bits % 1_000_000
78
+ sec = (bits / 1_000_000)
79
+ time = EPOCH_UTC + sec
80
+
81
+ Time.parse(
82
+ format(
83
+ '%<year>04d-%<mon>02d-%<day>02d %<hour>02d:%<min>02d:%<sec>02d.%<micro>06d +0000',
84
+ year: time.year,
85
+ mon: time.month,
86
+ day: time.day,
87
+ hour: time.hour,
88
+ min: time.min,
89
+ sec: time.sec,
90
+ micro: micro
91
+ )
92
+ )
93
+ end
94
+
36
95
  def _to_hugeint_from_vector(lower, upper)
37
96
  (upper << HALF_HUGEINT_BIT) + lower
38
97
  end
@@ -3,5 +3,5 @@
3
3
  module DuckDB
4
4
  # The version string of ruby-duckdb.
5
5
  # Currently, ruby-duckdb is NOT semantic versioning.
6
- VERSION = '1.0.0.0'
6
+ VERSION = '1.0.0.2'
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duckdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.0
4
+ version: 1.0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaki Suketa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-08 00:00:00.000000000 Z
11
+ date: 2024-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
181
  - !ruby/object:Gem::Version
182
182
  version: '0'
183
183
  requirements: []
184
- rubygems_version: 3.5.9
184
+ rubygems_version: 3.5.11
185
185
  signing_key:
186
186
  specification_version: 4
187
187
  summary: This module is Ruby binding for DuckDB database engine.