Module: Oinky::Model

Defined in:
lib/oinky/dsl.rb,
lib/oinky/compiler.rb,
lib/oinky/modelbase.rb,
lib/oinky/normalize.rb,
lib/oinky/rb_emitter.rb,
lib/oinky/cpp_emitter.rb

Defined Under Namespace

Modules: Internal, Schema, Table Classes: Cpp, DerivedType, Ruby

Constant Summary collapse

DefaultsByType =
{
  :string=>'',
  :bit=>false,
  :int8=>0,
  :int16=>0,
  :int32=>0,
  :int64=>0,
  :uint8=>0,
  :uint16=>0,
  :uint32=>0,
  :uint64=>0,
  :float32=>0.0,
  :float64=>0.0,
  :variant=>0,
  :datetime=>DateTime.parse("0001-01-01T00:00:00 UTC")
}

Class Method Summary collapse

Class Method Details

.build_schema(name, base = {}, &b) ⇒ Object

Build an entire schema



144
145
146
147
148
# File 'lib/oinky/dsl.rb', line 144

def self.build_schema(name, base = {}, &b)
  s = Internal::SchemaBuilder.new(name, base)
  s.instance_eval &b
  return s.to_h
end

.build_schema_adapter(name, base = {}, &b) ⇒ Object

Build an entire schema, generate a ruby adapter class, and evaluate it



151
152
153
154
155
# File 'lib/oinky/dsl.rb', line 151

def self.build_schema_adapter(name, base = {}, &b)
  s = build_schema(name, base, &b)
  cls = eval Oinky::Model.generate(s, :ruby)
  return cls
end

.build_table(name, base = {}) ⇒ Object

Someone may want to create an unbound table-def and then reuse it later in multiple schemas, or as a base definition for derived tables.



160
161
162
163
164
165
# File 'lib/oinky/dsl.rb', line 160

def self.build_table(name, base = {})
  s = Internal::TableBuilder.new(base)
  s.name(name)
  s.instance_eval &Proc.new
  s.to_h
end

.generate(schema, ccls) ⇒ Object



66
67
68
69
70
# File 'lib/oinky/compiler.rb', line 66

def self.generate(schema, ccls)
  # Allow specification by class or symbol
  ccls = ({:cpp=>Cpp, :CPP=>Cpp, :ruby=>Ruby, :rb=>Ruby}[ccls] || ccls)
  ccls.new(schema).emit
end

.normalize_column_def(nm, v) ⇒ Object

Raises:

  • (ArgumentError)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/oinky/normalize.rb', line 37

def self.normalize_column_def(nm, v)
  if v.is_a? Symbol
    validate_type(v)
    return {:type=>v, :default=>DefaultsByType[v], :accessor=>nm}
  end
  # Otherwise v is a hash
  validate_keys(v,[:type,:default,:accessor])
  t = v[:type]
  raise ArgumentError.new("No column type specified for column [#{nm}]") unless t
  v[:default] = DefaultsByType[t] unless v.has_key?(:default)
  # the accessor is only used for some target languages
  v[:accessor] = nm unless v.has_key?(:accessor)
  return v
end

.normalize_index_column_def(cd) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/oinky/normalize.rb', line 52

def self.normalize_index_column_def(cd)
  if cd.is_a?(Symbol)
    cd = cd.to_s
  end
  if cd.is_a?(String)
    # ascending is the default
    return {:name=>cd, :ascending=>true}
  end
  cd[:ascending] = true unless cd.has_key?(:ascending)
  validate_keys(cd,[:name,:ascending])
  return cd
end

.normalize_index_def(k, v) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/oinky/normalize.rb', line 65

def self.normalize_index_def(k,v)
  validate_keys(v,[:unique,:columns,:accessor, :name])
  if v.has_key?(:name) and (k.to_s != v[:name].to_s)
    raise ArgumentError.new("Inconsistent names for index: [#{k}] and [#{v[:name]}].")
  end
  d = {}
  d[:unique] = (v[:unique] or false)
  d[:accessor] = (v[:accessor] or k.to_s)
  d[:columns] = v[:columns].map{|cd| 
      normalize_index_column_def(cd)
    }
  return d
end

.normalize_schema(s) ⇒ Object

Raises:

  • (ArgumentError)


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/oinky/normalize.rb', line 104

def self.normalize_schema(s)
  validate_keys(s,[:name, :tables, :version, :classname])
  raise ArgumentError.new("Invalid schema definition") unless
    s[:name] and s[:name].size and s[:tables] and s[:version]
  
  tbls = {}
  if s[:tables].is_a? Hash
    s[:tables].each{|k,v|
        tbls[k.to_s] = normalize_table_schema(k.to_s, v)
      }
  else
    s[:tables].each{|v|
        nm = v[:name].to_s
        tbls[nm] = normalize_table_schema(nm, v)
      }
  end

  extras = {}
  extras[:classname] = s[:classname] if s.has_key?(:classname) 

  return {
      :name=>s[:name].to_s,
      :tables=>tbls,
      :version=>s[:version]
    }.merge(extras)
end

.normalize_table_schema(nm, h) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/oinky/normalize.rb', line 79

def self.normalize_table_schema(nm, h)
  cols = {}
  # columns is a hash of column_name=>defn
  h[:columns].each{|k,v|
      cn = k.to_s
      cols[cn] = normalize_column_def(cn, v)
    }

  ixs = {}
  h[:indices].each{|k,v|
      ixs[k.to_s] = normalize_index_def(k,v)
    }
  
  if h.has_key?(:name) and (nm.to_s != h[:name].to_s)
    raise ArgumentError.new("Inconsistent names for table: [#{nm}] and [#{h[:name]}].")
  end

  return {
      :name=>nm.to_s,
      :accessor=>(h[:accessor] or nm).to_s,
      :columns=>cols,
      :indices=>ixs
    }
end

.validate_keys(h, keys) ⇒ Object



23
24
25
26
27
28
29
30
# File 'lib/oinky/normalize.rb', line 23

def self.validate_keys(h, keys)
  h.keys.each{|k,v|
      unless keys.find_index(k)
        raise ArgumentError.new("Unrecognized key in Oinky schema " +
                                "definition: #{k}")
      end
    }
end

.validate_type(t) ⇒ Object



31
32
33
34
35
# File 'lib/oinky/normalize.rb', line 31

def self.validate_type(t)
  unless DefaultsByType.has_key?(t)
    raise ArgumentError.new("Unrecognized type in Oinky schema definition: #{k}")
  end
end