skydb 0.2.1 → 0.2.2

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.
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