skydb 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/bin/sky +85 -0
  2. data/lib/ext/hash.rb +11 -0
  3. data/lib/ext/treetop.rb +19 -0
  4. data/lib/skydb.rb +10 -3
  5. data/lib/skydb/client.rb +92 -28
  6. data/lib/skydb/import.rb +7 -0
  7. data/lib/skydb/import/importer.rb +258 -0
  8. data/lib/skydb/import/transforms/sky.yml +20 -0
  9. data/lib/skydb/import/transforms/snowplow.yml +1 -0
  10. data/lib/skydb/import/translator.rb +119 -0
  11. data/lib/skydb/message.rb +17 -12
  12. data/lib/skydb/message/create_table.rb +64 -0
  13. data/lib/skydb/message/delete_table.rb +66 -0
  14. data/lib/skydb/message/get_table.rb +74 -0
  15. data/lib/skydb/message/lookup.rb +79 -0
  16. data/lib/skydb/property.rb +5 -5
  17. data/lib/skydb/query.rb +198 -0
  18. data/lib/skydb/query/after.rb +103 -0
  19. data/lib/skydb/query/ast/selection_field_syntax_node.rb +26 -0
  20. data/lib/skydb/query/ast/selection_fields_syntax_node.rb +16 -0
  21. data/lib/skydb/query/ast/selection_group_syntax_node.rb +16 -0
  22. data/lib/skydb/query/ast/selection_groups_syntax_node.rb +16 -0
  23. data/lib/skydb/query/selection.rb +268 -0
  24. data/lib/skydb/query/selection_field.rb +74 -0
  25. data/lib/skydb/query/selection_fields_grammar.treetop +46 -0
  26. data/lib/skydb/query/selection_fields_parse_error.rb +30 -0
  27. data/lib/skydb/query/selection_group.rb +57 -0
  28. data/lib/skydb/query/selection_groups_grammar.treetop +31 -0
  29. data/lib/skydb/query/selection_groups_parse_error.rb +30 -0
  30. data/lib/skydb/query/validation_error.rb +8 -0
  31. data/lib/skydb/table.rb +69 -0
  32. data/lib/skydb/version.rb +1 -1
  33. data/test/import/importer_test.rb +42 -0
  34. data/test/import/translator_test.rb +88 -0
  35. data/test/message/add_event_message_test.rb +1 -1
  36. data/test/message/add_property_message_test.rb +2 -2
  37. data/test/message/create_table_message_test.rb +34 -0
  38. data/test/message/delete_table_message_test.rb +34 -0
  39. data/test/message/get_table_message_test.rb +19 -0
  40. data/test/message/lookup_message_test.rb +27 -0
  41. data/test/message_test.rb +1 -1
  42. data/test/query/after_test.rb +71 -0
  43. data/test/query/selection_test.rb +273 -0
  44. data/test/query_test.rb +156 -0
  45. data/test/test_helper.rb +3 -0
  46. metadata +129 -3
@@ -0,0 +1,20 @@
1
+ fields:
2
+ object_id: object_id:int
3
+ timestamp: timestamp:date
4
+
5
+ translate: |
6
+ input.each_pair do |k, v|
7
+ m, prefix, field, data_type = *k.match(/^(?:(action|data)\.)?(\w+)(?:\:(\w+))?$/)
8
+ next unless ["object_id", "timestamp"].index(field).nil?
9
+
10
+ output[prefix] ||= {} unless prefix.nil?
11
+ target = prefix.nil? ? output : output[prefix]
12
+
13
+ target[field] = case data_type.to_s.downcase
14
+ when "int" then v.to_i
15
+ when "float" then v.to_f
16
+ when "boolean" then (v.downcase == "true" || v.downcase == "yes" || v.downcase == "y")
17
+ when "date" then Chronic.parse(v)
18
+ else v.to_s
19
+ end
20
+ end
@@ -0,0 +1 @@
1
+ fields:
@@ -0,0 +1,119 @@
1
+ require 'chronic'
2
+
3
+ class SkyDB
4
+ class Import
5
+ class Translator
6
+ ##########################################################################
7
+ #
8
+ # Constructor
9
+ #
10
+ ##########################################################################
11
+
12
+ # Initializes the translator.
13
+ def initialize(options={})
14
+ self.input_field = options[:input_field]
15
+ self.output_field = options[:output_field]
16
+ self.format = options[:format]
17
+ self.translate_function = options[:translate_function]
18
+ end
19
+
20
+
21
+ ##########################################################################
22
+ #
23
+ # Attributes
24
+ #
25
+ ##########################################################################
26
+
27
+ # The name of the input field to read from.
28
+ attr_accessor :input_field
29
+
30
+ # The name of the output field to write to.
31
+ attr_accessor :output_field
32
+
33
+ # The format of the field (String, Integer, Float, Date).
34
+ attr_reader :format
35
+
36
+ def format=(value)
37
+ value = 'string' if value.nil?
38
+ value = 'int' if value == 'integer'
39
+ @format = value.to_s.downcase
40
+ end
41
+
42
+ # The translation function to execute. This can be a Proc or it can be
43
+ # a String that is evaluated into a proc with "input" and "output"
44
+ # arguments.
45
+ attr_reader :translate_function
46
+
47
+ def translate_function=(value)
48
+ # Only allow nils, procs & strings.
49
+ if !value.nil? && !value.is_a?(Proc) && !value.is_a?(String)
50
+ raise "Unable to convert #{value.class} to a translation function."
51
+ end
52
+
53
+ # If this is a string then eval it into a proc.
54
+ if value.is_a?(String)
55
+ # If there's no output field set then it's free form.
56
+ if output_field.nil?
57
+ @translate_function = eval("lambda { |input,output| #{value} }")
58
+
59
+ # If there is an output field set then make the lamda an assignment.
60
+ else
61
+ keys = output_field.is_a?(Array) ? output_field : [output_field]
62
+ keys.map! {|key| "['" + key.gsub("'", "\\'") + "']"}
63
+ @translate_function = eval("lambda { |input,output| output#{keys.join('')} = #{value.to_s} }")
64
+ end
65
+
66
+ # If this is a proc or a nil then just pass it through.
67
+ else
68
+ @translate_function = value
69
+ end
70
+ end
71
+
72
+
73
+ ##########################################################################
74
+ #
75
+ # Methods
76
+ #
77
+ ##########################################################################
78
+
79
+ # Translate a field from the input hash into a field into the
80
+ # output hash.
81
+ #
82
+ # @param [Hash] the input data.
83
+ # @param [Hash] the output data.
84
+ def translate(input, output)
85
+ # If a translation function is set then use it.
86
+ if !translate_function.nil?
87
+ translate_function.call(input, output)
88
+
89
+ # If the input field and output field are set then apply them.
90
+ elsif !input_field.nil? && !output_field.nil?
91
+ value = input[input_field]
92
+
93
+ # Navigate down to nested output hash if necessary.
94
+ if output_field.is_a?(Array)
95
+ output_field[0..-2].each do |field|
96
+ output[field] = {} unless output.has_key?(field)
97
+ output = output[field]
98
+ end
99
+
100
+ output_field = self.output_field.last
101
+ else
102
+ output_field = self.output_field
103
+ end
104
+
105
+ # Convert type.
106
+ output[output_field] = case format
107
+ when "int" then value.to_i
108
+ when "float" then value.to_f
109
+ when "boolean" then (value.downcase == "true" || value.downcase == "yes" || value.downcase == "y")
110
+ when "date" then Chronic.parse(value)
111
+ else value.to_s
112
+ end
113
+ end
114
+
115
+ return nil
116
+ end
117
+ end
118
+ end
119
+ end
data/lib/skydb/message.rb CHANGED
@@ -18,9 +18,9 @@ class SkyDB
18
18
  ##########################################################################
19
19
 
20
20
  # Initializes the message.
21
- def initialize(name)
22
- @name = name
23
- @table = ""
21
+ def initialize(message_name)
22
+ @message_name = message_name
23
+ @table_name = ""
24
24
  end
25
25
 
26
26
 
@@ -35,18 +35,18 @@ class SkyDB
35
35
  ####################################
36
36
 
37
37
  # The name of message being sent. This is defined by the subclass.
38
- attr_reader :name
38
+ attr_reader :message_name
39
39
 
40
40
 
41
41
  ####################################
42
- # Table
42
+ # Table Name
43
43
  ####################################
44
44
 
45
45
  # The name of the table the message is being sent to/from.
46
- attr_accessor :table
46
+ attr_accessor :table_name
47
47
 
48
- def table=(value)
49
- @table = value.to_s
48
+ def table_name=(value)
49
+ @table_name = value.to_s
50
50
  end
51
51
 
52
52
 
@@ -68,8 +68,8 @@ class SkyDB
68
68
  # Validates that the message is ready to be sent. If any validation issues
69
69
  # are found then an error is raised.
70
70
  def validate!
71
- if require_table? && (table.nil? || table.empty?)
72
- raise SkyDB::TableRequiredError.new('Table required')
71
+ if require_table? && (table_name.nil? || table_name.empty?)
72
+ raise SkyDB::TableRequiredError.new('Table name required')
73
73
  end
74
74
  end
75
75
 
@@ -97,8 +97,8 @@ class SkyDB
97
97
  def encode_header(buffer)
98
98
  buffer << [
99
99
  SkyDB::Message::VERSION,
100
- name,
101
- table
100
+ message_name,
101
+ table_name
102
102
  ].to_msgpack
103
103
  end
104
104
 
@@ -123,6 +123,10 @@ class SkyDB
123
123
  end
124
124
  end
125
125
 
126
+ require 'skydb/message/create_table'
127
+ require 'skydb/message/delete_table'
128
+ require 'skydb/message/get_table'
129
+
126
130
  require 'skydb/message/add_action'
127
131
  require 'skydb/message/get_action'
128
132
  require 'skydb/message/get_actions'
@@ -137,4 +141,5 @@ require 'skydb/message/next_actions'
137
141
  require 'skydb/message/lua/aggregate'
138
142
 
139
143
  require 'skydb/message/ping'
144
+ require 'skydb/message/lookup'
140
145
  require 'skydb/message/multi'
@@ -0,0 +1,64 @@
1
+ class SkyDB
2
+ class Message
3
+ class CreateTable < SkyDB::Message
4
+ ########################################################################
5
+ #
6
+ # Constructor
7
+ #
8
+ ########################################################################
9
+
10
+ # Initializes the 'create table' message.
11
+ #
12
+ # @param [Table] table the table to create.
13
+ def initialize(table=nil, options={})
14
+ super('create_table')
15
+ self.table = table
16
+ end
17
+
18
+
19
+ ##########################################################################
20
+ #
21
+ # Attributes
22
+ #
23
+ ##########################################################################
24
+
25
+ ##################################
26
+ # Table
27
+ ##################################
28
+
29
+ # The talbe to add.
30
+ attr_reader :table
31
+
32
+ def table=(value)
33
+ @table = value.is_a?(Table) ? value : nil
34
+ end
35
+
36
+
37
+ ##########################################################################
38
+ #
39
+ # Methods
40
+ #
41
+ ##########################################################################
42
+
43
+ ##################################
44
+ # Validation
45
+ ##################################
46
+
47
+ # A flag stating if the table is required for this type of message.
48
+ def require_table?
49
+ return false
50
+ end
51
+
52
+ ####################################
53
+ # Encoding
54
+ ####################################
55
+
56
+ # Encodes the message body.
57
+ #
58
+ # @param [IO] buffer the buffer to write the header to.
59
+ def encode_body(buffer)
60
+ buffer << table.to_msgpack
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,66 @@
1
+ class SkyDB
2
+ class Message
3
+ class DeleteTable < SkyDB::Message
4
+ ########################################################################
5
+ #
6
+ # Constructor
7
+ #
8
+ ########################################################################
9
+
10
+ # Initializes the 'delete table' message.
11
+ #
12
+ # @param [Table] table the table to delete.
13
+ def initialize(table=nil, options={})
14
+ super('delete_table')
15
+ self.table = table
16
+ end
17
+
18
+
19
+ ##########################################################################
20
+ #
21
+ # Attributes
22
+ #
23
+ ##########################################################################
24
+
25
+ ##################################
26
+ # Table
27
+ ##################################
28
+
29
+ # The talbe to add.
30
+ attr_reader :table
31
+
32
+ def table=(value)
33
+ @table = value.is_a?(Table) ? value : nil
34
+ end
35
+
36
+
37
+ ##########################################################################
38
+ #
39
+ # Methods
40
+ #
41
+ ##########################################################################
42
+
43
+ ##################################
44
+ # Validation
45
+ ##################################
46
+
47
+ # A flag stating if the table is required for this type of message.
48
+ def require_table?
49
+ return false
50
+ end
51
+
52
+ ####################################
53
+ # Encoding
54
+ ####################################
55
+
56
+ # Encodes the message body.
57
+ #
58
+ # @param [IO] buffer the buffer to write the header to.
59
+ def encode_body(buffer)
60
+ buffer << {
61
+ name: table.name
62
+ }.to_msgpack
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,74 @@
1
+ class SkyDB
2
+ class Message
3
+ class GetTable < SkyDB::Message
4
+ ########################################################################
5
+ #
6
+ # Constructor
7
+ #
8
+ ########################################################################
9
+
10
+ # Initializes the 'get_table' message.
11
+ #
12
+ # @param [Fixnum] name the name of the table to retrieve.
13
+ def initialize(name=nil, options={})
14
+ super('get_table')
15
+ self.name = name
16
+ end
17
+
18
+
19
+ ##########################################################################
20
+ #
21
+ # Attributes
22
+ #
23
+ ##########################################################################
24
+
25
+ ##################################
26
+ # Name
27
+ ##################################
28
+
29
+ # The name of the table to retrieve.
30
+ attr_reader :name
31
+
32
+ def name=(value)
33
+ @name = value.to_s
34
+ end
35
+
36
+
37
+ ##########################################################################
38
+ #
39
+ # Methods
40
+ #
41
+ ##########################################################################
42
+
43
+ ##################################
44
+ # Validation
45
+ ##################################
46
+
47
+ # A flag stating if the table is required for this type of message.
48
+ def require_table?
49
+ return false
50
+ end
51
+
52
+ ####################################
53
+ # Encoding
54
+ ####################################
55
+
56
+ # Encodes the message body.
57
+ #
58
+ # @param [IO] buffer the buffer to write the header to.
59
+ def encode_body(buffer)
60
+ buffer << {
61
+ name: name
62
+ }.to_msgpack
63
+ end
64
+
65
+ def process_response(response)
66
+ if !response.nil? && !response['table'].nil?
67
+ response = SkyDB::Table.new(response['table']['name'])
68
+ else
69
+ return nil
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,79 @@
1
+ class SkyDB
2
+ class Message
3
+ class Lookup < SkyDB::Message
4
+ ########################################################################
5
+ #
6
+ # Constructor
7
+ #
8
+ ########################################################################
9
+
10
+ # Initializes the 'lookup' message.
11
+ def initialize(options={})
12
+ super('lookup')
13
+ self.actions = options[:actions] || []
14
+ self.properties = options[:properties] || []
15
+ end
16
+
17
+
18
+ ##########################################################################
19
+ #
20
+ # Attributes
21
+ #
22
+ ##########################################################################
23
+
24
+ ##################################
25
+ # Actions
26
+ ##################################
27
+
28
+ # A list of actions to lookup.
29
+ attr_accessor :actions
30
+
31
+ # A list of properties to lookup.
32
+ attr_accessor :properties
33
+
34
+
35
+ ##########################################################################
36
+ #
37
+ # Methods
38
+ #
39
+ ##########################################################################
40
+
41
+ ####################################
42
+ # Encoding
43
+ ####################################
44
+
45
+ # Encodes the message body.
46
+ #
47
+ # @param [IO] buffer the buffer to write the header to.
48
+ def encode_body(buffer)
49
+ buffer << {
50
+ 'actionNames' => actions.map {|action| action.name},
51
+ 'propertyNames' => properties.map {|property| property.name}
52
+ }.to_msgpack
53
+ end
54
+
55
+ ####################################
56
+ # Response processing
57
+ ####################################
58
+
59
+ # Updates the action and property identifiers from the returned data.
60
+ def process_response(response)
61
+ # Update actions.
62
+ actions.each_with_index do |action, index|
63
+ obj = response['actions'][index]
64
+ action.id = obj.nil? ? 0 : obj['id']
65
+ end
66
+
67
+ # Update properties.
68
+ properties.each_with_index do |property, index|
69
+ obj = response['properties'][index]
70
+ property.id = obj.nil? ? 0 : obj['id']
71
+ property.type = obj.nil? ? :object : SkyDB::Property::Type.decode(obj['type'])
72
+ property.data_type = obj.nil? ? nil : obj['dataType']
73
+ end
74
+
75
+ return response
76
+ end
77
+ end
78
+ end
79
+ end