mohair 0.0.2 → 0.0.3

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/.gitignore CHANGED
@@ -19,3 +19,4 @@ Gemfile.lock
19
19
  .yardoc
20
20
  _yardoc
21
21
  doc/
22
+ vendor
data/Gemfile CHANGED
@@ -4,4 +4,7 @@ gemspec
4
4
 
5
5
  # Specify your gem's dependencies in mohair.gemspec
6
6
  gem "riak-client"
7
-
7
+ gem "parslet"
8
+ gem "rake"
9
+ # gem "treetop"
10
+ gem 'json', '~> 1.7.7'
data/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # Mohair
2
2
 
3
- TODO: Write a gem description
4
-
5
3
  ## Installation
6
4
 
7
5
  Add this line to your application's Gemfile:
@@ -18,7 +16,40 @@ Or install it yourself as:
18
16
 
19
17
  ## Usage
20
18
 
21
- TODO: Write usage instructions here
19
+ now:
20
+
21
+ ```
22
+ $ bundle exec bin/mohair -q "select all from sometable" -i INDEX
23
+ $ bundle exec bin/mohair_dump < data.json
24
+ ```
25
+
26
+ future:
27
+
28
+ ```
29
+ $ bundle exec bin/mohair -i
30
+ mohair> select * from sometable
31
+ mohair> insert * into ...
32
+ mohair>
33
+ ```
34
+
35
+ ```
36
+ $ bundle exec bin/mohair -q "select * from sometable"
37
+ ...
38
+ ```
39
+
40
+ ## Currently works
41
+
42
+ - basic SQL parsing
43
+ - select * from table
44
+ - select col,col,col from table [where col = "name" and col < 23] [group by col]
45
+
46
+ ## TODO
47
+
48
+ - group by
49
+ - limit 10
50
+ - asc/desc
51
+ - 2i
52
+ - query optimization
22
53
 
23
54
  ## Contributing
24
55
 
@@ -27,3 +58,7 @@ TODO: Write usage instructions here
27
58
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
59
  4. Push to the branch (`git push origin my-new-feature`)
29
60
  5. Create new Pull Request
61
+
62
+ ```
63
+ $ bundle exec rake release
64
+ ```
data/Rakefile CHANGED
@@ -1,3 +1,13 @@
1
1
  require "bundler/gem_tasks"
2
2
  require 'bundler'
3
- Bundler::GemHelper.install_tasks
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rake/testtask'
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << 'lib' << 'test'
9
+ t.test_files = FileList['test/plugin/*.rb']
10
+ t.verbose = true
11
+ end
12
+
13
+ task :default => :test
data/bin/mohair_dump ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mohair'
4
+
5
+ Mohair::do_dump()
@@ -0,0 +1,39 @@
1
+ require 'mohair'
2
+ require 'riak'
3
+
4
+ module Mohair
5
+ class Inserter
6
+ def initialize bucket_name
7
+ @bucket_name = bucket_name
8
+ end
9
+ def insert_all objs
10
+ @client = Riak::Client.new(:protocol => "http")
11
+ bucket = @client.bucket(@bucket_name)
12
+ if bucket.props["allow_mult"] then
13
+ $stderr.puts "allow_mult should be false (how to handle siblilngs?)"
14
+ return
15
+ end
16
+
17
+ objs.each do |obj|
18
+ r_o = Riak::RObject.new(bucket, obj["key"])
19
+
20
+ data = r_o.data = obj["data"]
21
+ obj["data"].each do |k,v|
22
+ begin
23
+ if integer? v then r_o.indexes[k + "_int"] << v end
24
+ rescue
25
+ r_o.indexes[k + "_bin"] << v
26
+ end
27
+ end
28
+ r_o.content_type = 'application/json'
29
+ r_o.store
30
+ print obj["key"] , "\t => ", data, "\n"
31
+ end
32
+ end
33
+
34
+ def exec!
35
+ end
36
+ def pr
37
+ end
38
+ end
39
+ end
@@ -1,43 +1,148 @@
1
1
  require 'mohair'
2
+ require 'riak'
3
+ require 'erb'
2
4
 
3
5
  module Mohair
4
- class Selector
5
- def initialize argv
6
- @cols = []
7
- @from = []
8
- @where = []
9
- argv.shift
10
- parse_first argv
11
- end
12
- def parse_first tokens
13
- token = tokens.shift.downcase
14
- case token.downcase
15
- when 'from'
16
- parse_from tokens
17
- when 'where'
18
- parse_where tokens
19
- else
20
- @cols << token
21
- parse_first tokens
6
+
7
+ MapperTemplate = <<EOMAP
8
+ function(v){
9
+ var f = function(key, obj){
10
+ var ret = {};
11
+ <% select.each do |c| %>
12
+ <%= c %>
13
+ <% end %>
14
+ ret.__key = key;
15
+ <%= where %>
16
+ };
17
+ var raw_obj = JSON.parse(v.values[0].data);
18
+ if(raw_obj instanceof Array){
19
+ var ret0 = [];
20
+ for(var i in raw_obj){
21
+ ret0 = ret0.concat(f(v.key, raw_obj[i]));
22
+ }
23
+ return ret0;
24
+ }else{
25
+ return f(v.key, raw_obj);
26
+ }
27
+ }
28
+ EOMAP
29
+
30
+ ReducerTemplate = <<EOREDUCE
31
+ function(values){
32
+ var ret = {};
33
+ // init lines
34
+ <%= agg_init %>
35
+ for(var i in values){
36
+ var v=values[i];
37
+ <%= agg_fun %>
38
+ }
39
+ return [ret];
40
+ }
41
+ EOREDUCE
42
+ # if(!!(v.sum_age)){ ret.sum_age += v.sum_age; }
43
+
44
+ GetAllMapper = <<GETALLMAPPER
45
+ function(v){
46
+ var f = function(key, obj){
47
+ var ret = obj;
48
+ ret.__key = key;
49
+ <%= where %>
50
+ };
51
+ var raw_obj = JSON.parse(v.values[0].data);
52
+ if(raw_obj instanceof Array){
53
+ var ret0 = [];
54
+ for(var i in raw_obj){
55
+ ret0 = ret0.concat(f(v.key, raw_obj[i]));
56
+ }
57
+ return ret0;
58
+ }else{
59
+ return f(v.key, raw_obj);
60
+ }
61
+ }
62
+ GETALLMAPPER
63
+
64
+ GroupByMapperTemplate = <<EOGROUPER
65
+ function(v){
66
+ ejsLog('/tmp/map_reduce.log', "startmapper>")
67
+ var f = function(key, obj){
68
+ var ret = {};
69
+ <% select.each do |c| %>
70
+ <%= c %>
71
+ <% end %>
72
+ ret.__key = key;
73
+ <%= where %>
74
+ };
75
+ var arr = [];
76
+ var raw_obj = JSON.parse(v.values[0].data);
77
+ if(raw_obj instanceof Array){
78
+ var ret0 = [];
79
+ for(var i in raw_obj){
80
+ ret0 = ret0.concat(f(v.key, raw_obj[i]));
81
+ }
82
+ arr = ret0;
83
+ }else{
84
+ arr = f(v.key, raw_obj);
85
+ }
86
+ var ret = {};
87
+ for(var i in arr){
88
+ //ejsLog('/tmp/map_reduce.log', JSON.stringify(arr[i].<%= col %>))
89
+ var col = arr[i].<%= col %>;
90
+ //ejsLog('/tmp/map_reduce.log', JSON.stringify(col))
91
+ if(ret[col]){
92
+ ret[col] = ret[col].push(arr[i]);
93
+ //ejsLog('/tmp/map_reduce.log', JSON.stringify(ret[col]))
94
+ }else{
95
+ ret[col] = [arr[i]];
96
+ //ejsLog('/tmp/map_reduce.log', JSON.stringify(ret[col]))
97
+ }
98
+ }
99
+ ejsLog('/tmp/map_reduce.log', "<eomapper")
100
+ return [ret];
101
+ }
102
+ EOGROUPER
103
+
104
+
105
+ ## merge them all
106
+ ## [{ k, v }, ....] -> {k, v}
107
+ GroupByReducerTemplate = <<EOREDUCEGROUPER
108
+ function(values){
109
+ ejsLog('/tmp/map_reduce.log', "start>");
110
+ var ret = {};
111
+ for(var i in values){
112
+ ejsLog('/tmp/map_reduce.log', JSON.stringify(i))
113
+ for(var a in values[i]){
114
+ if(ret[a]){
115
+ ret[a] = ret[a].concat(values[i][a]);
116
+ }else{
117
+ ret[a] = values[i][a];
118
+ }
119
+ }
120
+ }
121
+ ejsLog('/tmp/map_reduce.log', "<end");
122
+ // ejsLog('/tmp/map_reduce.log', JSON.stringify(ret))
123
+ return [ret];
124
+ }
125
+ EOREDUCEGROUPER
126
+
127
+
128
+ def Mohair.format_result results
129
+ columns = Set.new
130
+ results.each do |r|
131
+ r.each do |k,v|
132
+ columns.add(k)
22
133
  end
23
134
  end
24
- def parse_from tokens
25
- token = tokens.shift.downcase
26
- p token
27
- case token.downcase
28
- when 'where'
29
- parse_where tokens
30
- else
31
- @from << token
135
+ columns.delete('__key')
136
+ cols = columns.to_a.join("\t| ")
137
+ print "| | #{cols}|\n"
138
+ print "+---------------+------------------------------+\n"
139
+ results.each do |r|
140
+ print "| #{r['__key']}\t| "
141
+ columns.to_a.each do |c|
142
+ print "#{r[c]} \t| "
32
143
  end
33
- end
34
- def parse_where tokens
35
- end
36
- def exec!
37
- pr
38
- end
39
- def pr
40
- print "<select> #{@cols} <from> #{@from};\n"
144
+ print "\n"
41
145
  end
42
146
  end
147
+
43
148
  end
@@ -0,0 +1,88 @@
1
+
2
+ require "rubygems"
3
+ require "parslet"
4
+
5
+ module Mohair
6
+ module Sql
7
+ class Parser < Parslet::Parser
8
+ rule(:integer) { match('[0-9]').repeat(1) }
9
+ #rule(:float) { integer.repeat >> str('.') >> integer.maybe }
10
+
11
+ rule(:space) { match('\s').repeat(1) }
12
+ rule(:space?) { space.maybe }
13
+ rule(:comma) { str(',') >> space? }
14
+ rule(:lparen) { str('(') >> space? }
15
+ rule(:rparen) { str(')') >> space? }
16
+
17
+ # logical operators
18
+ rule(:eq) { str('=') }
19
+ rule(:neq) { str('!=') | str('<>') }
20
+ rule(:gt) { str('>') }
21
+ rule(:lt) { str('<') }
22
+ rule(:geq) { str('>=') }
23
+ rule(:leq) { str('<=') }
24
+ rule(:btw) { str('between') }
25
+ #rule(:like) { str('like') >> space? }
26
+ rule(:binop) { eq | neq | gt | lt | geq | leq | btw}
27
+
28
+ rule(:string) { str('"') >> match('[a-zA-Z0-9]').repeat >> str('"') }
29
+
30
+ rule(:const) {
31
+ integer | string
32
+ }
33
+ rule(:term) { const | item }
34
+
35
+ rule(:bool_and) { str('and') }
36
+ rule(:bool_or) { str('or') }
37
+
38
+
39
+ rule(:identifier) { match('[a-z]').repeat(1) }
40
+
41
+ rule(:function) {
42
+ identifier.as(:function) >> space? >>
43
+ lparen >> arglist.as(:arguments) >> rparen
44
+ }
45
+
46
+ rule(:item) { function | identifier }
47
+
48
+ rule(:arglist) {
49
+ item.as(:item) >> (comma >> item.as(:item)).repeat
50
+ }
51
+ rule(:namelist) {
52
+ identifier.as(:name) >> (comma >> identifier.as(:name)).repeat
53
+ }
54
+
55
+ rule(:single_cond){
56
+ term.as(:lhs) >> space? >> binop.as(:op) >> space? >> term.as(:rhs)
57
+ }
58
+
59
+ rule(:condition) {
60
+ single_cond.as(:lhs) >> space? >>
61
+ ((bool_and.as(:op) | bool_or.as(:op)) >>
62
+ space? >>
63
+ condition.as(:rhs)).maybe
64
+ }
65
+
66
+ rule(:select_s) {
67
+ str('select').as(:op) >> space? >> (arglist | str('*')).as(:select)
68
+ }
69
+ rule(:from_s) {
70
+ str('from') >> space? >> namelist.as(:from)
71
+ }
72
+ rule(:where_s) {
73
+ str('where') >> space? >> condition.as(:where)
74
+ }
75
+ rule(:group_s) {
76
+ str('group') >> space? >> str('by') >> space? >> item.as(:group_by)
77
+ }
78
+ rule(:select) {
79
+ select_s >> space? >> from_s >> space? >>
80
+ (where_s >> space? >> group_s.maybe | group_s).maybe
81
+ }
82
+ ## limit 10 desc by 'col'
83
+
84
+ rule(:expression) { select } #| insert | create }
85
+ root :expression
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,93 @@
1
+ require 'mohair/selector'
2
+
3
+ module Mohair
4
+ class Select
5
+ def initialize tree
6
+ @select = build_columns tree[:select]
7
+ @from = From.new tree[:from]
8
+ @where = Where.new tree[:where]
9
+ @group_by = Group.new tree[:group_by]
10
+ @agg = false
11
+ end
12
+
13
+ def build_columns items
14
+ reqs = []
15
+ if items.class == Array then
16
+ items.each do |i|
17
+ reqs << maybe_column(i[:item])
18
+ end
19
+ elsif items.class == Hash then
20
+ reqs << maybe_column(items[:item])
21
+ elsif items.to_s == "*" then
22
+ reqs = :all
23
+ end
24
+ reqs
25
+ end
26
+
27
+ def maybe_column item
28
+ if item.class == Hash then
29
+ if item[:function] then
30
+ Function.new item
31
+ else
32
+ raise item
33
+ end
34
+ else
35
+ Column.new item
36
+ end
37
+ end
38
+
39
+ def bucket
40
+ @from.bucket
41
+ end
42
+
43
+ def mapper
44
+ where = @where.to_js
45
+
46
+ ## don't do 'select * from table group by col'
47
+ if @select == :all then
48
+ ERB.new(GetAllMapper).result(binding)
49
+
50
+ elsif @group_by and @group_by.col then
51
+ select = []
52
+ col = @group_by.col
53
+ @select.each do |c| select << c.to_map_js end
54
+ ERB.new(GroupByMapperTemplate).result(binding)
55
+
56
+ else
57
+ select = []
58
+ @select.each do |c| select << c.to_map_js end
59
+ ERB.new(MapperTemplate).result(binding)
60
+
61
+ end
62
+ end
63
+
64
+ def reducer
65
+ if @select == :all then
66
+ return nil
67
+ end
68
+ if @group_by and @group_by.col then
69
+ col = @group_by.col
70
+ return ERB.new(GroupByReducerTemplate).result(binding)
71
+ end
72
+
73
+ @select.each do |c|
74
+ if c.is_agg? then
75
+ agg_init, agg_fun = c.to_reduce_js
76
+ return ERB.new(ReducerTemplate).result(binding)
77
+ end
78
+ end
79
+ return nil
80
+ end
81
+
82
+ end
83
+
84
+ def any(arr, fun)
85
+ arr.each do |e|
86
+ if fun(e) then
87
+ return true
88
+ end
89
+ end
90
+ return false
91
+ end
92
+
93
+ end
@@ -0,0 +1,197 @@
1
+ ## syntax tree
2
+ require 'mohair/sql/select'
3
+
4
+ module Mohair
5
+
6
+ def Mohair.build tree
7
+ case tree[:op]
8
+ when 'select'
9
+ Select.new tree
10
+ when 'insert'
11
+ Insert.new tree
12
+ when 'update'
13
+ Update.new tree
14
+ when 'delete'
15
+ Delete.new tree
16
+ else
17
+ LOG.error "bad :op", tree
18
+ end
19
+ end
20
+
21
+
22
+ class Column
23
+ def initialize item
24
+ @name = item.to_s
25
+ end
26
+
27
+ def to_map_js
28
+ "ret.#{@name} = obj.#{@name};"
29
+ end
30
+
31
+ def is_agg?
32
+ false
33
+ end
34
+ end
35
+
36
+ class Function
37
+ def initialize item
38
+ @name = item[:function].to_s
39
+ @argv = []
40
+ if item[:arguments] == Array then
41
+ item[:arguments].each do |i|
42
+ @argv << i[:item].to_s
43
+ end
44
+ else
45
+ @argv << item[:arguments][:item]
46
+ end
47
+ end
48
+
49
+ def to_map_js
50
+ s = @argv[0]
51
+ case @name
52
+ when 'sum' then
53
+ "ret.sum_#{s} = obj.#{s};"
54
+ when 'avg' then
55
+ "ret.sum_#{s} = obj.#{s};\n ret.count_#{s} = 1;"
56
+ when 'count' then
57
+ if s == 'key' then
58
+ "if(!!(v.#{s})){ ret.count_#{s} = 1; }"
59
+ else
60
+ "if(!!(obj.#{s})){ ret.count_#{s} = 1; }"
61
+ end
62
+ end
63
+ end
64
+
65
+ def to_reduce_js
66
+
67
+ s = @argv[0]
68
+ case @name
69
+ when 'sum' then
70
+ ["ret.sum_#{s} = 0;", "if(!!(v.sum_#{s})){ ret.sum_#{s} += v.sum_#{s}; }"]
71
+ when 'avg' then
72
+ ["ret.sum_#{s} = 0; ret.count_#{s} = 0;",
73
+ "if(!!(v.sum_#{s})){ ret.sum_#{s} += v.sum_#{s};\n ret.count_#{s} += v.count_#{s}; }"]
74
+ when 'count' then
75
+ ["ret.count_#{s} = 0;",
76
+ "if(!!(v.count_#{s})){ ret.count_#{s} += v.count_#{s}; }"]
77
+ end
78
+
79
+ end
80
+
81
+ def is_agg?
82
+ true
83
+ end
84
+ end
85
+
86
+ class Insert
87
+ end
88
+
89
+ class Update
90
+ end
91
+
92
+ class Delete
93
+ end
94
+
95
+ class From
96
+ def initialize tree
97
+ @name = tree[:name]
98
+ end
99
+ def bucket
100
+ @name.to_s
101
+ end
102
+ end
103
+
104
+ class Condition
105
+ def initialize tree
106
+ if tree[:rhs].nil? && tree[:lhs].class == Hash then
107
+ tree = tree[:lhs]
108
+ end
109
+ lhs = tree[:lhs]
110
+ rhs = tree[:rhs]
111
+ @op = tree[:op].to_s
112
+
113
+ if lhs.class == Hash then
114
+ @lhs = Condition.new lhs
115
+ elsif (lhs.to_s =~ /^[0-9]+$/).nil? then
116
+ @lhs = lhs.to_s
117
+ else
118
+ @lhs = lhs.to_i
119
+ end
120
+
121
+ if rhs.class == Hash then
122
+ @rhs = Condition.new rhs
123
+ elsif (rhs.to_s =~ /^[0-9]+$/).nil? then
124
+ @rhs = rhs.to_s
125
+ else
126
+ @rhs = rhs.to_i
127
+ end
128
+ end
129
+
130
+ def to_js
131
+ lhs = rhs = nil
132
+ if @rhs.class == Fixnum then
133
+ rhs = @rhs
134
+ elsif @rhs.class == Condition then
135
+ rhs = "( #{@rhs.to_js} )"
136
+ elsif (@rhs[0] == "\"" and @rhs[-1] == "\"") then
137
+ rhs = @rhs
138
+ else
139
+ rhs = "obj.#{@rhs}"
140
+ end
141
+ if @lhs.class == Fixnum then
142
+ lhs = @lhs
143
+ elsif @lhs.class == Condition then
144
+ lhs = "( #{@lhs.to_js} )"
145
+ elsif (@lhs[0] == "\"" and @lhs[-1] == "\"") then
146
+ lhs = @lhs
147
+ else
148
+ lhs = "obj.#{@lhs}"
149
+ end
150
+ " (#{lhs}) #{operator2str(@op)} (#{rhs}) "
151
+ end
152
+
153
+ def operator2str op
154
+ ## SQL to JS operator
155
+ case op
156
+ when '=' then '=='
157
+ when '<>' then '!='
158
+ when "and" then '&&'
159
+ when 'or' then '||'
160
+ else op
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ class Where
167
+ def initialize tree
168
+ if tree then
169
+ @cond = Condition.new tree
170
+ else
171
+ @cond = nil
172
+ end
173
+ end
174
+ def to_js
175
+ if @cond.nil? then
176
+ "return [ret];"
177
+ else
178
+ s = @cond.to_js
179
+ "if(#{s}){ return [ret]; }else{ return[]; }"
180
+ end
181
+ end
182
+ end
183
+
184
+ class Order
185
+ end
186
+
187
+ class Group
188
+ def initialize col
189
+ @col = col.to_s
190
+ end
191
+
192
+ def col
193
+ @col
194
+ end
195
+ end
196
+
197
+ end
@@ -1,3 +1,3 @@
1
1
  module Mohair
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/mohair.rb CHANGED
@@ -1,17 +1,87 @@
1
+ require "mohair/sql/parser"
2
+ require "mohair/sql/tree"
3
+
1
4
  require "mohair/version"
2
5
  require "mohair/selector"
6
+ require "mohair/inserter"
7
+
8
+ require "json"
9
+ require "optparse"
10
+ require "logger"
11
+
12
+ LOG = Logger.new(STDERR)
13
+ LOG.level = Logger::DEBUG # WARN, INFO, DEBUG, ...
3
14
 
4
15
  module Mohair
5
- # Your code goes here...
16
+
17
+ def self.usage
18
+ print <<EOS
19
+ usage:
20
+ $ mohair -q "select foo, bar from bucket_name" [-i INDEX]
21
+ $ mohair_dump <bucket_name> < sample_data.json
22
+
23
+ insert, delete sentence is future work
24
+ mohair version #{Mohair::VERSION}
25
+ EOS
26
+ exit -1
27
+ end
28
+
6
29
  def self.main
7
- case ARGV[0].downcase
30
+
31
+ q = nil #query!!
32
+ index = nil
33
+
34
+ opt = OptionParser.new
35
+ opt.on('-q Q'){|v| q = v}
36
+ opt.on('-i INDEX'){|v| index = v}
37
+ opt.on('-h', '--help'){ usage }
38
+
39
+ opt.parse!(ARGV)
40
+
41
+ parser = Sql::Parser.new
42
+ sql_syntax_tree = parser.parse (q.strip)
43
+ LOG.debug sql_syntax_tree
44
+
45
+ case sql_syntax_tree[:op]
8
46
  when 'select'
9
- Selector.new(ARGV).exec!
10
- when 'insert'
11
- when 'show'
12
- when 'create'
47
+
48
+ s = (Mohair.build sql_syntax_tree)
49
+
50
+ LOG.debug "mapper->\n"
51
+ LOG.debug s.mapper
52
+ LOG.debug "reducer->\n"
53
+ LOG.debug s.reducer
54
+
55
+ client = Riak::Client.new(:protocol => "http")
56
+ bucket = Riak::MapReduce.new(client)
57
+ .add(client.bucket(s.bucket))## keyfilsters and so on here
58
+
59
+ reducer = s.reducer
60
+ result = nil
61
+ if reducer.nil? then
62
+ result = bucket.map(s.mapper, :keep => true)
63
+ .run
64
+ else
65
+ result = bucket.map(s.mapper, :keep => false)
66
+ .reduce(reducer, :keep => true)
67
+ .run
68
+ end
69
+
70
+ #LOG.debug "raw query result> #{result}"
71
+ LOG.info "query result:"
72
+ format_result result
73
+
74
+ # when :insert
75
+ # when :show
76
+ when :create
77
+ LOG.error "CREATE sentence is unavailable at mohair"
13
78
  else
14
- print "bad query: ", ARGV, "\n"
79
+ LOG.error "bad query: ", result, "\n"
15
80
  end
16
81
  end
82
+
83
+ def self.do_dump
84
+ objs = JSON.load(STDIN)
85
+ Inserter.new(ARGV[0]).insert_all(objs)
86
+ end
17
87
  end
data/sample_data.json ADDED
@@ -0,0 +1,40 @@
1
+ [{
2
+ "key" : "ham",
3
+ "data" : {
4
+ "name" : "john smith",
5
+ "age" : 42,
6
+ "gender" : "male"
7
+ }
8
+ },
9
+ {
10
+ "key" : "hamspam",
11
+ "data" : {
12
+ "name" : "john smith",
13
+ "age" : 42,
14
+ "gender" : "male"
15
+ }
16
+ },
17
+ {
18
+ "key" : "eggspam",
19
+ "data" : {
20
+ "name" : "joanna smith",
21
+ "age" : 42,
22
+ "gender" : "female"
23
+ }
24
+ },
25
+ {
26
+ "key" : "adam_smith2",
27
+ "data" : {
28
+ "name" : "john smith",
29
+ "age" : 42,
30
+ "gender" : "male"
31
+ }
32
+ },
33
+ {
34
+ "key" : "adam_smith",
35
+ "data" : {
36
+ "name" : "Adam smith",
37
+ "age" : 456,
38
+ "gender" : "male"
39
+ }
40
+ }]
@@ -0,0 +1,10 @@
1
+ require 'test/unit'
2
+
3
+ class SelectorTest < MiniTest::Unit::TestCase
4
+ def setup
5
+ end
6
+ def teardown
7
+ end
8
+ def test_one
9
+ end
10
+ end
@@ -0,0 +1,73 @@
1
+ require 'test_helper'
2
+ # require 'parslet'
3
+
4
+ class ParserTest < MiniTest::Unit::TestCase
5
+ #include Mohair
6
+
7
+ def setup
8
+ @parser = Mohair::Sql::Parser.new
9
+ end
10
+ def teardown
11
+ end
12
+ def test_simples # check syntax parser with parslet
13
+ [
14
+ 'select a from b',
15
+ 'select a, b from comme',
16
+ 'select b from far',
17
+ 'select c from d',
18
+ 'select a, c, d,e,f,f from b ',
19
+ 'select count(a) from d',
20
+ ].each do |sql|
21
+ s = @parser.parse sql
22
+ assert_equal(expected = "select", actual = s[:op])
23
+ assert(! s[:select].nil?)
24
+ assert(! s[:from].nil?)
25
+ assert(! (Mohair.build s).nil?)
26
+ end
27
+ end
28
+
29
+ def test_bad_sql
30
+ [
31
+ 'select',
32
+ ' select a from b',
33
+ ].each do |bad_sql|
34
+ assert_raises Parslet::ParseFailed do
35
+ @parser.parse bad_sql
36
+ end
37
+ end
38
+ end
39
+
40
+ def test_where
41
+ [
42
+ 'select a from b where a > 20',
43
+ 'select a,b from c where a = 20',
44
+ 'select a,b from c where 20 < a and b < 234',
45
+ 'select a,b from c where 20 < a or b = 234',
46
+ 'select a, b from c where a = "oo"',
47
+ 'select a, b from c where a = "oo" and c > 235',
48
+ ].each do |where_sql|
49
+ s = @parser.parse where_sql
50
+ assert_equal(expected = "select", actual = s[:op])
51
+ assert(! s[:select].nil?)
52
+ assert(! s[:from].nil?)
53
+ assert(! s[:where].nil?)
54
+ assert(! (Mohair.build s).nil?)
55
+ end
56
+ end
57
+
58
+ def test_group_by
59
+ [
60
+ 'select a from b group by c',
61
+ 'select a from b where a > 345 group by c',
62
+ 'select a from b where a > 345 and foo = "hoge" group by c',
63
+ ].each do |where_sql|
64
+ s = @parser.parse where_sql
65
+ assert_equal(expected = "select", actual = s[:op])
66
+ assert(! s[:select].nil?)
67
+ assert(! s[:from].nil?)
68
+ assert(! s[:group_by].nil?)
69
+ assert(! (Mohair.build s).nil?)
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,5 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'test/unit'
5
+ require 'mohair'
metadata CHANGED
@@ -1,8 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mohair
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 25
4
5
  prerelease:
5
- version: 0.0.2
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
6
11
  platform: ruby
7
12
  authors:
8
13
  - UENISHI Kota
@@ -10,7 +15,7 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2013-03-18 00:00:00 Z
18
+ date: 2013-05-25 00:00:00 Z
14
19
  dependencies: []
15
20
 
16
21
  description: a new type of Riak client
@@ -18,6 +23,7 @@ email:
18
23
  - kuenishi@gmail.com
19
24
  executables:
20
25
  - mohair
26
+ - mohair_dump
21
27
  extensions: []
22
28
 
23
29
  extra_rdoc_files: []
@@ -29,10 +35,19 @@ files:
29
35
  - README.md
30
36
  - Rakefile
31
37
  - bin/mohair
38
+ - bin/mohair_dump
32
39
  - lib/mohair.rb
40
+ - lib/mohair/inserter.rb
33
41
  - lib/mohair/selector.rb
42
+ - lib/mohair/sql/parser.rb
43
+ - lib/mohair/sql/select.rb
44
+ - lib/mohair/sql/tree.rb
34
45
  - lib/mohair/version.rb
35
46
  - mohair.gemspec
47
+ - sample_data.json
48
+ - test/plugin/selector.rb
49
+ - test/plugin/sql.rb
50
+ - test/test_helper.rb
36
51
  homepage: ""
37
52
  licenses: []
38
53
 
@@ -46,19 +61,27 @@ required_ruby_version: !ruby/object:Gem::Requirement
46
61
  requirements:
47
62
  - - ">="
48
63
  - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
49
67
  version: "0"
50
68
  required_rubygems_version: !ruby/object:Gem::Requirement
51
69
  none: false
52
70
  requirements:
53
71
  - - ">="
54
72
  - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
55
76
  version: "0"
56
77
  requirements: []
57
78
 
58
79
  rubyforge_project:
59
- rubygems_version: 1.8.23
80
+ rubygems_version: 1.8.25
60
81
  signing_key:
61
82
  specification_version: 3
62
83
  summary: a new type of a riak client
63
- test_files: []
64
-
84
+ test_files:
85
+ - test/plugin/selector.rb
86
+ - test/plugin/sql.rb
87
+ - test/test_helper.rb