Module: Avro::SchemaCompatibility

Defined in:
lib/avro/schema_compatibility.rb

Defined Under Namespace

Classes: Checker

Constant Summary collapse

INT_COERCIBLE_TYPES_SYM =
[:long, :float, :double].freeze
LONG_COERCIBLE_TYPES_SYM =
[:float, :double].freeze

Class Method Summary collapse

Class Method Details

.can_read?(writers_schema, readers_schema) ⇒ Boolean

Perform a full, recursive check that a datum written using the writers_schema can be read using the readers_schema.

Returns:

  • (Boolean)


24
25
26
# File 'lib/avro/schema_compatibility.rb', line 24

def self.can_read?(writers_schema, readers_schema)
  Checker.new.can_read?(writers_schema, readers_schema)
end

.match_schemas(writers_schema, readers_schema) ⇒ Object

Perform a basic check that a datum written with the writers_schema could be read using the readers_schema. This check includes matching the types, including schema promotion, and matching the full name (including aliases) for named types.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/avro/schema_compatibility.rb', line 37

def self.match_schemas(writers_schema, readers_schema)
  # Bypass deeper checks if the schemas are the same Ruby objects
  return true if writers_schema.equal?(readers_schema)

  w_type = writers_schema.type_sym
  r_type = readers_schema.type_sym

  # This conditional is begging for some OO love.
  if w_type == :union || r_type == :union
    return true
  end

  if w_type == r_type
    return readers_schema.match_schema?(writers_schema) if Schema::PRIMITIVE_TYPES_SYM.include?(r_type)

    case r_type
    when :request
      return true
    when :map
      return match_schemas(writers_schema.values, readers_schema.values)
    when :array
      return match_schemas(writers_schema.items, readers_schema.items)
    else
      return readers_schema.match_schema?(writers_schema)
    end
  end

  # Handle schema promotion
  # rubocop:disable Lint/DuplicateBranch
  if w_type == :int && INT_COERCIBLE_TYPES_SYM.include?(r_type)
    return true
  elsif w_type == :long && LONG_COERCIBLE_TYPES_SYM.include?(r_type)
    return true
  elsif w_type == :float && r_type == :double
    return true
  elsif w_type == :string && r_type == :bytes
    return true
  elsif w_type == :bytes && r_type == :string
    return true
  end
  # rubocop:enable Lint/DuplicateBranch

  if readers_schema.respond_to?(:match_schema?)
    readers_schema.match_schema?(writers_schema)
  else
    false
  end
end

.mutual_read?(writers_schema, readers_schema) ⇒ Boolean

Perform a full, recursive check that a datum written using either the writers_schema or the readers_schema can be read using the other schema.

Returns:

  • (Boolean)


30
31
32
# File 'lib/avro/schema_compatibility.rb', line 30

def self.mutual_read?(writers_schema, readers_schema)
  Checker.new.mutual_read?(writers_schema, readers_schema)
end