From 92a3e0b4c92e6e369096efe28ccb50ccb074b331 Mon Sep 17 00:00:00 2001 From: Lud Date: Fri, 20 Sep 2024 19:48:49 +0200 Subject: [PATCH 1/3] fix: don't treat vectors as jsonb --- lib/kirei/model/class_methods.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/kirei/model/class_methods.rb b/lib/kirei/model/class_methods.rb index be886ba..60234f4 100644 --- a/lib/kirei/model/class_methods.rb +++ b/lib/kirei/model/class_methods.rb @@ -86,11 +86,22 @@ def wrap_jsonb_non_primivitives!(attributes) attributes.each_pair do |key, value| next unless value.is_a?(Hash) || value.is_a?(Array) + next if vector_column?(key.to_s) attributes[key] = T.unsafe(Sequel).pg_jsonb_wrap(value) end end + # New method to check if a column is a vector type + sig { params(column_name: String).returns(T::Boolean) } + def vector_column?(column_name) + _col_name, col_info = T.let( + db.schema(table_name.to_sym).find { _1[0] == column_name.to_sym }, + [Symbol, T::Hash[Symbol, T.untyped]] + ) + col_info.fetch(:db_type).match?(/vector\(\d+\)/) + end + sig do override.params( hash: T::Hash[Symbol, T.untyped], From 0befbd9b71202b105231422c80688e2524d2cfd4 Mon Sep 17 00:00:00 2001 From: Lud Date: Fri, 20 Sep 2024 20:16:00 +0200 Subject: [PATCH 2/3] must cast vectors --- lib/kirei/model/class_methods.rb | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/kirei/model/class_methods.rb b/lib/kirei/model/class_methods.rb index 60234f4..69badb9 100644 --- a/lib/kirei/model/class_methods.rb +++ b/lib/kirei/model/class_methods.rb @@ -85,14 +85,19 @@ def wrap_jsonb_non_primivitives!(attributes) return unless App.config.db_extensions.include?(:pg_json) attributes.each_pair do |key, value| - next unless value.is_a?(Hash) || value.is_a?(Array) - next if vector_column?(key.to_s) - - attributes[key] = T.unsafe(Sequel).pg_jsonb_wrap(value) + if vector_column?(key.to_s) + attributes[key] = cast_to_vector(value) + elsif value.is_a?(Hash) || value.is_a?(Array) + attributes[key] = T.unsafe(Sequel).pg_jsonb_wrap(value) + end end end - # New method to check if a column is a vector type + # + # install the gem "pgvector" if you need to use vector columns + # also add `:pgvector` to the `App.config.db_extensions` array + # and enable the vector extension on the database. + # sig { params(column_name: String).returns(T::Boolean) } def vector_column?(column_name) _col_name, col_info = T.let( @@ -102,6 +107,17 @@ def vector_column?(column_name) col_info.fetch(:db_type).match?(/vector\(\d+\)/) end + # New method to cast an array to a vector + sig { params(value: T.any(T::Array[Numeric], Sequel::SQL::Expression)).returns(Sequel::SQL::Expression) } + def cast_to_vector(value) + return value if value.is_a?(Sequel::SQL::Expression) || value.is_a?(Sequel::SQL::PlaceholderLiteralString) + Kernel.raise("'pg_array' extension is not enabled") unless db.extension(:pg_array) + + pg_array = T.unsafe(Sequel).pg_array(value) + + Sequel.lit("?::vector", pg_array) + end + sig do override.params( hash: T::Hash[Symbol, T.untyped], From 3f952e7e9dc9f549939756658c9ffbb046c8c4a2 Mon Sep 17 00:00:00 2001 From: Lud Date: Fri, 20 Sep 2024 20:58:53 +0200 Subject: [PATCH 3/3] rubocop --- .rubocop.yml | 2 +- lib/kirei/model/class_methods.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 3481691..59e8ebd 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -36,7 +36,7 @@ Metrics/MethodLength: - 'method_call' Metrics/ModuleLength: - Max: 100 + Max: 150 CountAsOne: - 'array' - 'heredoc' diff --git a/lib/kirei/model/class_methods.rb b/lib/kirei/model/class_methods.rb index 69badb9..95aa746 100644 --- a/lib/kirei/model/class_methods.rb +++ b/lib/kirei/model/class_methods.rb @@ -102,7 +102,7 @@ def wrap_jsonb_non_primivitives!(attributes) def vector_column?(column_name) _col_name, col_info = T.let( db.schema(table_name.to_sym).find { _1[0] == column_name.to_sym }, - [Symbol, T::Hash[Symbol, T.untyped]] + [Symbol, T::Hash[Symbol, T.untyped]], ) col_info.fetch(:db_type).match?(/vector\(\d+\)/) end @@ -111,6 +111,7 @@ def vector_column?(column_name) sig { params(value: T.any(T::Array[Numeric], Sequel::SQL::Expression)).returns(Sequel::SQL::Expression) } def cast_to_vector(value) return value if value.is_a?(Sequel::SQL::Expression) || value.is_a?(Sequel::SQL::PlaceholderLiteralString) + Kernel.raise("'pg_array' extension is not enabled") unless db.extension(:pg_array) pg_array = T.unsafe(Sequel).pg_array(value)