mohair 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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