Class: Piglet::Schema::Tuple

Inherits:
Object
  • Object
show all
Defined in:
lib/piglet/schema/tuple.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(field_names, type_map) ⇒ Tuple



8
9
10
11
12
13
# File 'lib/piglet/schema/tuple.rb', line 8

def initialize(field_names, type_map)
  @field_names = [ ]
  @field_names = field_names.dup if field_names
  @type_map = { }
  @type_map = type_map.dup if type_map
end

Instance Attribute Details

#field_namesObject (readonly)

Returns the value of attribute field_names.



6
7
8
# File 'lib/piglet/schema/tuple.rb', line 6

def field_names
  @field_names
end

Class Method Details

.parse(description) ⇒ Object

Returns a new Tuple with a schema described by the specified array.

The array will be interpreted as follows: each element defines a field, and a field can have an optional type. To define a typeless field simply use a symbol, to define a typed field use an array with two values: the first is the name and the second is the type.

The type of a field can be one of the following:

  • :int

  • :long

  • :float

  • :double

  • :chararray

  • :bytearray

  • :tuple or Piglet::Schema::Tuple

  • :bag or Piglet::Schema::Bag

If a type is not given it defaults to :bytearray. To define a tuple field either pass a Piglet::Schema::Tuple object as the type, or use :tuple and a thrid element, which is the schema of the tuple, e.g. [[:a, :tuple, [:b, :c]]].

Maps are currently not supported.

Examples (Piglet schema description to the left with the Pig Latin schema definition to the right):

[:a, :b, :c]                     # => (a:bytearray, b:bytearray, c:bytearray)
[[:a, :chararray], [:b, :float]] # => (a:chararray, b:float)
[[:a, Tuple.parse(:b, :c)]]      # => (a:tuple (b:bytearray, c:bytearray))
[[:a, :bag, [:b, :c]]]           # => (a:bag {x:tuple (b:bytearray, c:bytearray)})


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
# File 'lib/piglet/schema/tuple.rb', line 46

def self.parse(description)
  field_names = [ ]
  type_map = { }
  index = 0
  description.map do |component|
    case component
    when Enumerable
      head = component.first
      tail = component[1..-1]
      case tail.first
      when :tuple
        type_map[head || index] = parse(*tail[1..-1])
      when :bag
        type_map[head || index] = Bag.new(parse(*tail[1..-1]))
      else
        type_map[head || index] = tail.first
      end
      field_names << head
    else
      type_map[component] = :bytearray
      field_names << component
    end
    index += 1
  end
  Tuple.new(field_names, type_map)
end

Instance Method Details

#field_type(field_name) ⇒ Object



85
86
87
88
89
90
# File 'lib/piglet/schema/tuple.rb', line 85

def field_type(field_name)
  if Integer === field_name
    field_name = @field_names[field_name] || field_name
  end
  @type_map[field_name]
end

#to_sObject



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/piglet/schema/tuple.rb', line 92

def to_s
  field_declarations = @field_names.map do |field_name|
    type = field_type(field_name)
    type_str = case type
    when Tuple
      "tuple #{type}"
    when Bag
      "bag #{type}"
    else
      type.to_s
    end
    if field_name
      "#{field_name}:#{type_str}"
    else
      type_str
    end
  end
  "(#{field_declarations.join(', ')})"
end

#union(*tuples) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/piglet/schema/tuple.rb', line 73

def union(*tuples)
  field_names = @field_names.dup
  type_map = @type_map.dup
  tuples.flatten.each do |tuple|
    tuple.field_names.each do |f|
      field_names << f
      type_map[f] = tuple.field_type(f)
    end
  end
  Tuple.new(field_names, type_map)
end