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.
- data/bin/sky +85 -0
- data/lib/ext/hash.rb +11 -0
- data/lib/ext/treetop.rb +19 -0
- data/lib/skydb.rb +10 -3
- data/lib/skydb/client.rb +92 -28
- data/lib/skydb/import.rb +7 -0
- data/lib/skydb/import/importer.rb +258 -0
- data/lib/skydb/import/transforms/sky.yml +20 -0
- data/lib/skydb/import/transforms/snowplow.yml +1 -0
- data/lib/skydb/import/translator.rb +119 -0
- data/lib/skydb/message.rb +17 -12
- data/lib/skydb/message/create_table.rb +64 -0
- data/lib/skydb/message/delete_table.rb +66 -0
- data/lib/skydb/message/get_table.rb +74 -0
- data/lib/skydb/message/lookup.rb +79 -0
- data/lib/skydb/property.rb +5 -5
- data/lib/skydb/query.rb +198 -0
- data/lib/skydb/query/after.rb +103 -0
- data/lib/skydb/query/ast/selection_field_syntax_node.rb +26 -0
- data/lib/skydb/query/ast/selection_fields_syntax_node.rb +16 -0
- data/lib/skydb/query/ast/selection_group_syntax_node.rb +16 -0
- data/lib/skydb/query/ast/selection_groups_syntax_node.rb +16 -0
- data/lib/skydb/query/selection.rb +268 -0
- data/lib/skydb/query/selection_field.rb +74 -0
- data/lib/skydb/query/selection_fields_grammar.treetop +46 -0
- data/lib/skydb/query/selection_fields_parse_error.rb +30 -0
- data/lib/skydb/query/selection_group.rb +57 -0
- data/lib/skydb/query/selection_groups_grammar.treetop +31 -0
- data/lib/skydb/query/selection_groups_parse_error.rb +30 -0
- data/lib/skydb/query/validation_error.rb +8 -0
- data/lib/skydb/table.rb +69 -0
- data/lib/skydb/version.rb +1 -1
- data/test/import/importer_test.rb +42 -0
- data/test/import/translator_test.rb +88 -0
- data/test/message/add_event_message_test.rb +1 -1
- data/test/message/add_property_message_test.rb +2 -2
- data/test/message/create_table_message_test.rb +34 -0
- data/test/message/delete_table_message_test.rb +34 -0
- data/test/message/get_table_message_test.rb +19 -0
- data/test/message/lookup_message_test.rb +27 -0
- data/test/message_test.rb +1 -1
- data/test/query/after_test.rb +71 -0
- data/test/query/selection_test.rb +273 -0
- data/test/query_test.rb +156 -0
- data/test/test_helper.rb +3 -0
- 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(
|
22
|
-
@
|
23
|
-
@
|
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 :
|
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 :
|
46
|
+
attr_accessor :table_name
|
47
47
|
|
48
|
-
def
|
49
|
-
@
|
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? && (
|
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
|
-
|
101
|
-
|
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
|