rails-paradedb 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 296e696bfa9711537e984df359c43be2481b53a91f75c880dc33ac36aacf4b1c
4
- data.tar.gz: 78781d5fc912c5b57053818d7f3e76e2d01251fb7d31a586edd5d28b88426e69
3
+ metadata.gz: 61970bcefe75f0514836a81ab38dd8e39fe1c6f311d55f35366120d2285325b9
4
+ data.tar.gz: 6179c3b6d0814dcaae1179977548c4b47e6f6447110596293f242d668727d79a
5
5
  SHA512:
6
- metadata.gz: 5b4fecd2d8620a91e782ea62df980ab6638fec2906ad5a380664e97b77a8d0e1b4b656aa330cc4b9e80a99e18f2223cd2d50da6cea98245c63c1c4fe88ca7450
7
- data.tar.gz: a6c42abf6b75aad3ee2d3b58651cfde545ba86deef7e33df0593cafc94da529818dbe41f290286e0acc3eb9bc62071d4d2b06d7976cb8c44d5a94be7c9a37722
6
+ metadata.gz: 38471cccf3d392cd481dbb22cde9f35c37f09a555c4e6081c5484d9c5ad1920082172276447a2401a22c0dd46bcd1a0846f2dee26678f556f913373996a91da0
7
+ data.tar.gz: 6176c6252901db66d8f8dd72972f8053fc6a187d0d10391705dde18fabe16a4992d60655a351b3af8643e9ca4a57c2baff58a11a2dd93cb63a708750785034c6
data/CHANGELOG.md CHANGED
@@ -2,7 +2,11 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
- ## [Unreleased]
5
+ ## [0.11.0] - 2026-08-04
6
+
7
+ ### Added
8
+
9
+ - Vector index build options `centroid_ratio`, `training_samples_per_centroid`, and `cluster_replication` in `ParadeDB::Index` `index_options` and `add_paradedb_index` (pg_search 0.25.0+). They are emitted in the `WITH (...)` clause and round-tripped through the schema dumper.
6
10
 
7
11
  [0.10.0] - 2026-08-04
8
12
 
@@ -170,7 +174,7 @@ All notable changes to this project will be documented in this file. The format
170
174
  - Schema dump/load round-trip for tokenizer configuration and index options
171
175
  (including `target_segment_count`)
172
176
 
173
- [Unreleased]: https://github.com/paradedb/rails-paradedb/compare/v0.10.0...HEAD
177
+ [0.11.0]: https://github.com/paradedb/rails-paradedb/releases/tag/v0.11.0
174
178
  [0.10.0]: https://github.com/paradedb/rails-paradedb/releases/tag/v0.10.0
175
179
  [0.9.0]: https://github.com/paradedb/rails-paradedb/releases/tag/v0.9.0
176
180
  [0.8.0]: https://github.com/paradedb/rails-paradedb/releases/tag/v0.8.0
@@ -83,6 +83,8 @@ module ParadeDB
83
83
  # Consumed by migration helpers; validates and normalizes the DSL class
84
84
  class DefinitionCompiler
85
85
  FIELD_OPTION_KEYS = %i[fast record normalizer expand_dots].freeze
86
+ INDEX_OPTION_KEYS = %i[target_segment_count centroid_ratio training_samples_per_centroid cluster_replication].freeze
87
+ POSITIVE_INTEGER_INDEX_OPTION_KEYS = %i[target_segment_count training_samples_per_centroid cluster_replication].freeze
86
88
 
87
89
  class Compiled
88
90
  attr_reader :table_name, :key_field, :index_name, :entries, :index_options, :field_options, :where
@@ -238,16 +240,26 @@ module ParadeDB
238
240
  memo[key.to_sym] = value
239
241
  end
240
242
 
241
- unknown = normalized.keys - [:target_segment_count]
243
+ unknown = normalized.keys - INDEX_OPTION_KEYS
242
244
  unless unknown.empty?
243
245
  raise InvalidIndexDefinition,
244
246
  "unknown index_options keys: #{unknown.map(&:inspect).join(', ')}"
245
247
  end
246
248
 
247
- if normalized.key?(:target_segment_count)
248
- target = normalized[:target_segment_count]
249
- unless target.is_a?(Integer) && target.positive?
250
- raise InvalidIndexDefinition, "index_options[:target_segment_count] must be an Integer > 0"
249
+ POSITIVE_INTEGER_INDEX_OPTION_KEYS.each do |key|
250
+ next unless normalized.key?(key)
251
+
252
+ value = normalized[key]
253
+ unless value.is_a?(Integer) && value.positive?
254
+ raise InvalidIndexDefinition, "index_options[#{key.inspect}] must be an Integer > 0"
255
+ end
256
+ end
257
+
258
+ if normalized.key?(:centroid_ratio)
259
+ ratio = normalized[:centroid_ratio]
260
+ unless ratio.is_a?(Numeric) && ratio >= 0.000001 && ratio <= 1.0
261
+ raise InvalidIndexDefinition,
262
+ "index_options[:centroid_ratio] must be a Numeric between 0.000001 and 1.0"
251
263
  end
252
264
  end
253
265
 
@@ -100,9 +100,12 @@ module ParadeDB
100
100
  options << "key_field=#{quote(compiled.key_field.to_s)}"
101
101
 
102
102
  compiled.index_options.each do |key, value|
103
- case key.to_sym
104
- when :target_segment_count
105
- options << "target_segment_count=#{Integer(value)}"
103
+ name = key.to_sym
104
+ case name
105
+ when :target_segment_count, :training_samples_per_centroid, :cluster_replication
106
+ options << "#{name}=#{Integer(value)}"
107
+ when :centroid_ratio
108
+ options << "centroid_ratio=#{Float(value)}"
106
109
  else
107
110
  raise ParadeDB::InvalidIndexDefinition, "unsupported index option #{key.inspect}"
108
111
  end
@@ -297,6 +300,7 @@ module ParadeDB
297
300
  c.relname AS index_name,
298
301
  t.relname AS table_name,
299
302
  pg_get_indexdef(c.oid) AS indexdef,
303
+ array_to_json(c.reloptions)::text AS reloptions,
300
304
  pg_get_expr(i.indpred, i.indrelid) AS where_clause
301
305
  FROM pg_class c
302
306
  JOIN pg_namespace n ON n.oid = c.relnamespace
@@ -319,7 +323,7 @@ module ParadeDB
319
323
  name = row["index_name"]
320
324
 
321
325
  key_field = extract_paradedb_key_field(indexdef)
322
- index_options = extract_paradedb_index_options(indexdef)
326
+ index_options = extract_paradedb_index_options(row["reloptions"])
323
327
  fields_sql = extract_paradedb_fields_sql(indexdef)
324
328
  where = normalize_paradedb_where_clause(row["where_clause"])
325
329
 
@@ -369,27 +373,30 @@ module ParadeDB
369
373
  nil
370
374
  end
371
375
 
372
- def extract_paradedb_index_options(indexdef)
373
- with_sql, = extract_paradedb_with_components(indexdef)
374
- options = {}
375
- split_sql_arguments(with_sql).each do |argument|
376
- key, value_sql = split_assignment(argument)
377
- next if key.nil?
378
- next if key == "key_field"
376
+ def extract_paradedb_index_options(reloptions)
377
+ paradedb_reloption_entries(reloptions).each_with_object({}) do |entry, options|
378
+ key, separator, value = entry.to_s.partition("=")
379
+ next if separator.empty?
379
380
 
380
381
  case key
381
- when "target_segment_count"
382
- parsed = parse_sql_literal(value_sql)
383
- if parsed.is_a?(Integer)
384
- options[:target_segment_count] = parsed
385
- elsif parsed.is_a?(String) && parsed.match?(/\A\d+\z/)
386
- options[:target_segment_count] = parsed.to_i
387
- end
382
+ when "target_segment_count", "training_samples_per_centroid", "cluster_replication"
383
+ parsed = Integer(value, 10, exception: false)
384
+ options[key.to_sym] = parsed if parsed
385
+ when "centroid_ratio"
386
+ parsed = Float(value, exception: false)
387
+ options[:centroid_ratio] = parsed if parsed
388
388
  end
389
389
  end
390
- options
391
- rescue
392
- {}
390
+ end
391
+
392
+ def paradedb_reloption_entries(reloptions)
393
+ case reloptions
394
+ when Array then reloptions
395
+ when String then Array(JSON.parse(reloptions))
396
+ else []
397
+ end
398
+ rescue JSON::ParserError
399
+ []
393
400
  end
394
401
 
395
402
  def extract_paradedb_fields_sql(indexdef)
@@ -410,27 +417,6 @@ module ParadeDB
410
417
  indexdef[start..pos - 2]
411
418
  end
412
419
 
413
- def extract_paradedb_with_components(indexdef)
414
- match = indexdef.match(/WITH\s*\(/im)
415
- start = match.end(0)
416
- depth = 1
417
- pos = start
418
- while pos < indexdef.length && depth > 0
419
- case indexdef[pos]
420
- when "(" then depth += 1
421
- when ")" then depth -= 1
422
- end
423
- pos += 1
424
- end
425
- raise "Found invalid index definition `#{indexdef}`" if depth != 0
426
-
427
- with_sql = indexdef[start..pos - 2]
428
- trailing_sql = indexdef[pos..]&.strip
429
- trailing_sql = nil if trailing_sql == ""
430
-
431
- [with_sql, trailing_sql]
432
- end
433
-
434
420
  def normalize_paradedb_where_clause(where)
435
421
  return nil if where.nil?
436
422
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ParadeDB
4
- VERSION = "0.10.0"
4
+ VERSION = "0.11.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-paradedb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ParadeDB