crate_ruby 0.0.2 → 0.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 89005d37bce3036b7cc74a9cf521a85493f8695e
4
- data.tar.gz: d92405d8c41d5c191cd6a943cc45a3227fd2c01b
3
+ metadata.gz: 4a726eb5a922ba00e842ae5128897f44ebc348ed
4
+ data.tar.gz: 0d3d601ffb7c5bbecfd3c6f80a55905b434559e7
5
5
  SHA512:
6
- metadata.gz: 7fc3c5596813c4de4565c91f4d4a8b8ff5447143a66734956fbf342d997209cde01b042949721184868948c916e0beabd0a985353722bbc7c5d7e17b5afce279
7
- data.tar.gz: f7dd74c16239b2e5f6bb5811529c44513b184c77a4849bf45431c4e3ddfa1bf6ebcb121ca71c4b044886f545ee48d1b02bf8cfdff7374b064877e50dcfec3d40
6
+ metadata.gz: 5a55318fc2253b2244ffe7ec3fa88496903ed9f42171b7b1b036f002ffd69e3e7781836678e5e7a1362cc2f20e79c44e3f2c6b69c5dbf5114ec26eade980c578
7
+ data.tar.gz: b09c8a6e7d4449746105721e8cc3903f7c18cd2231f2359c5e749cdc43f3af5c5c01a3197356d8e04d14c060b20ec2b6bc550ee912c32c723f8590e5650768e8
data/.gitignore CHANGED
@@ -18,3 +18,4 @@ tmp
18
18
  .idea/*
19
19
  .rvmrc
20
20
  log/crate.log
21
+ crate_test_server.*
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # CrateRuby
2
2
 
3
- Official ruby library to access a (Crate)[http://crate.io] database.
3
+ Official Ruby library to access a [Crate](http://crate.io) database.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,10 +8,6 @@ Add this line to your application's Gemfile:
8
8
 
9
9
  gem 'crate_ruby'
10
10
 
11
- And then execute:
12
-
13
- $ bundle
14
-
15
11
  Or install it yourself as:
16
12
 
17
13
  $ gem install crate_ruby
@@ -21,13 +17,15 @@ Or install it yourself as:
21
17
  ### Issueing SQL statements
22
18
  require 'crate_ruby'
23
19
 
24
- # optional args :host, :port, :logger
25
20
  client = CrateRuby::Client.new
21
+
26
22
  result = client.execute("Select * from posts")
27
23
  => #<CrateRuby::ResultSet:0x00000002a9c5e8 @rowcount=1, @duration=5>
24
+
28
25
  result.each do |row|
29
- puts row.inspect # [1, "test", 5]
26
+ puts row.inspect
30
27
  end
28
+ => [1, "test", 5]
31
29
 
32
30
  result.cols
33
31
  => ["id", "my_column", "my_integer_col"]
@@ -48,11 +46,26 @@ Or install it yourself as:
48
46
  #deletion
49
47
  client.blob_delete(table_name, digest)
50
48
 
49
+ ## Tests
50
+
51
+ To run the tests start up the crate server first
52
+
53
+ ruby spec/test_server.rb
54
+
51
55
  ## Contributing
52
56
 
53
- 1. Fork it ( http://github.com/<my-github-username>/crate_ruby/fork )
57
+ 1. Fork it ( `http://github.com/crate /crate_ruby/fork` )
54
58
  2. Create your feature branch (`git checkout -b my-new-feature`)
55
59
  3. Add some tests
56
60
  4. Commit your changes (`git commit -am 'Add some feature'`)
57
61
  5. Push to the branch (`git push origin my-new-feature`)
58
62
  6. Create new Pull Request
63
+
64
+ ##Maintainer
65
+
66
+ * [Christoph Klocker](http://www.vedanova.com), [@corck](http://www.twitter.com/corck)
67
+
68
+ ##License
69
+
70
+ MIT License. Copyright 2014 Vedanova. [http://vedanova.com](http://vedanova.com)
71
+
data/lib/crate_ruby.rb CHANGED
@@ -10,7 +10,7 @@ module CrateRuby
10
10
  @logger ||= begin
11
11
  require 'logger'
12
12
  log = Logger.new(File.join(File.dirname(__FILE__), "../log/crate.log"), 10, 1024000)
13
- log.level = Logger::DEBUG
13
+ log.level = Logger::INFO
14
14
  log
15
15
  end
16
16
  end
@@ -11,6 +11,7 @@ module CrateRuby
11
11
  # @param [Array] servers An Array of servers including ports [127.0.0.1:4200, 10.0.0.1:4201]
12
12
  # @param [opts] Optional paramters
13
13
  # * logger: Custom Logger
14
+ # @return [CrateRuby::Client]
14
15
  def initialize(servers = [], opts = {})
15
16
  @servers = servers
16
17
  @servers << "#{DEFAULT_HOST}:#{DEFAULT_PORT}" if servers.empty?
@@ -18,7 +19,7 @@ module CrateRuby
18
19
  end
19
20
 
20
21
  def inspect
21
- %Q{#<CrateRuby::Client:#{object_id}, @uri="#{@uri}">}
22
+ %Q{#<CrateRuby::Client:#{object_id}>}
22
23
  end
23
24
 
24
25
  # Creates a table
@@ -26,7 +27,7 @@ module CrateRuby
26
27
  # @param [String] table_name
27
28
  # @param [Hash] column_definition
28
29
  # @option column_definition [String] key sets column name, value sets column type. an array passed as value can be used to set options like primary keys
29
- # @return [Boolean]
30
+ # @return [ResultSet]
30
31
  #
31
32
  def create_table(table_name, column_definition = {}, blob=false)
32
33
  cols = column_definition.to_a.map { |a| a.join(' ') }.join(', ')
@@ -38,7 +39,7 @@ module CrateRuby
38
39
  # @param [String] name Table name
39
40
  # @param [Integer] shard Shard count, defaults to 5
40
41
  # @param [Integer] number Number of replicas, defaults to 0
41
- # @return [Boolean]
42
+ # @return [ResultSet]
42
43
  #
43
44
  # client.create_blob_table("blob_table")
44
45
  def create_blob_table(name, shard_count=5, replicas=0)
@@ -49,7 +50,7 @@ module CrateRuby
49
50
  # Drop table
50
51
  # @param [String] table_name, Name of table to drop
51
52
  # @param [Boolean] blob Needs to be set to true if table is a blob table
52
- # @return [Boolean]
53
+ # @return [ResultSet]
53
54
  def drop_table(table_name, blob=false)
54
55
  tbl = blob ? "BLOB TABLE" : "TABLE"
55
56
  stmt = %Q{DROP #{tbl} "#{table_name}"}
@@ -59,25 +60,30 @@ module CrateRuby
59
60
  # List all user tables
60
61
  # @return [ResultSet]
61
62
  def show_tables
62
- execute("select * from information_schema.tables where schema_name = 'doc'")
63
+ execute("select table_name from information_schema.tables where schema_name = 'doc'")
64
+ end
65
+
66
+ # Returns all tables in schema 'doc'
67
+ # @return [Array] Array of table names
68
+ def tables
69
+ execute("select table_name from information_schema.tables where schema_name = 'doc'").map(&:first)
63
70
  end
64
71
 
65
72
  # Executes a SQL statement against the Crate HTTP REST endpoint.
66
73
  # @param [String] sql statement to execute
67
- # @return [ResultSet, false]
74
+ # @return [ResultSet]
68
75
  def execute(sql)
76
+ @logger.debug sql
69
77
  req = Net::HTTP::Post.new("/_sql", initheader = {'Content-Type' => 'application/json'})
70
78
  req.body = {"stmt" => sql}.to_json
71
79
  response = request(req)
80
+ @logger.debug response.body
72
81
  success = case response.code
73
- when "200"
82
+ when /^2\d{2}/
74
83
  ResultSet.new response.body
75
- when "400"
76
- @logger.info(response.body)
77
- false
78
84
  else
79
85
  @logger.info(response.body)
80
- false
86
+ raise CrateRuby::CrateError.new(response.body)
81
87
  end
82
88
  success
83
89
  end
@@ -141,6 +147,30 @@ module CrateRuby
141
147
  success
142
148
  end
143
149
 
150
+
151
+ # Return the table structure
152
+ # @param [String] table_name Table name to get structure
153
+ # @param [ResultSet]
154
+ def table_structure(table_name)
155
+ execute("select * from information_schema.columns where schema_name = 'doc' AND table_name = '#{table_name}'")
156
+ end
157
+
158
+
159
+ def insert(table_name, attributes)
160
+ vals = attributes.values.map { |x| x.is_a?(String) ? "'#{x}'" : x }.join(', ')
161
+ stmt = %Q{INSERT INTO "#{table_name}" (#{attributes.keys.join(', ')}) VALUES (#{vals})}
162
+ execute(stmt)
163
+ end
164
+
165
+ # Crate is eventually consistent, If you don't query by primary key,
166
+ # it is not guaranteed that an insert record is found on the next
167
+ # query. Default refresh value is 1000ms.
168
+ # Using refresh_table you can force a refresh
169
+ # @param [String] table_name Name of table to refresh
170
+ def refresh_table(table_name)
171
+ execute "refresh table #{table_name}"
172
+ end
173
+
144
174
  private
145
175
 
146
176
  def blob_path(table, digest)
@@ -151,7 +181,7 @@ module CrateRuby
151
181
  host, port = @servers.first.split(':');
152
182
  Net::HTTP.new(host, port)
153
183
  end
154
-
184
+
155
185
  def request(req)
156
186
  connection.start { |http| http.request(req) }
157
187
  end
@@ -4,7 +4,7 @@ module CrateRuby
4
4
 
5
5
  attr_reader :rowcount, :duration, :cols
6
6
 
7
- # @param [String] Crate result
7
+ # @param [String] result
8
8
  def initialize(result)
9
9
  result = JSON.parse(result)
10
10
  @cols = result['cols']
@@ -23,13 +23,17 @@ module CrateRuby
23
23
 
24
24
  def each(&block)
25
25
  @rows.each(&block)
26
- nil
27
26
  end
28
27
 
29
28
  def [](val)
30
29
  @rows[val]
31
30
  end
32
31
 
32
+ # @return [Array] Returns all rows as Array of arrays
33
+ def values
34
+ @rows
35
+ end
36
+
33
37
  # @param [Array] ary Column names to filer on
34
38
  # @return [Array] Filtered rows
35
39
  def select_columns(ary, &block)
@@ -1,3 +1,3 @@
1
1
  module CrateRuby
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -1,47 +1,46 @@
1
1
  require_relative '../spec_helper'
2
2
 
3
3
  describe CrateRuby::Client do
4
+ TABLE_NAME = 'blob_table'
4
5
  describe '#create_table' do
5
- let(:client) { CrateRuby::Client.new }
6
+ let(:client) { CrateRuby::Client.new(["localhost:#{TEST_PORT}"]) }
6
7
 
7
- describe 'blob mangament' do
8
- let(:table_name) { 'blob_table' }
8
+ describe 'blob management' do
9
9
  let(:file) { 'logo-crate.png' }
10
- #let(:file) { 'text.txt' }
11
10
  let(:path) { File.join(File.dirname(__FILE__), '../uploads/') }
12
11
  let(:file_path) { File.join(path, file) }
13
12
  let(:digest) { Digest::SHA1.file(file_path).hexdigest }
14
13
  let(:store_location) { File.join(path, "get_#{file}") }
15
14
 
16
- before do
17
- client.execute("create blob TABLE #{table_name}")
15
+ before(:all) do
16
+ CrateRuby::Client.new(["localhost:#{TEST_PORT}"]).execute("create blob TABLE #{TABLE_NAME}")
18
17
  end
19
18
 
20
- after do
21
- client.execute("drop blog TABLE #{table_name}")
19
+ after(:all) do
20
+ CrateRuby::Client.new(["localhost:#{TEST_PORT}"]).execute("drop blob TABLE #{TABLE_NAME}")
22
21
  end
23
22
 
24
23
  describe '#blob_put' do
25
24
 
26
25
  after do
27
- client.blob_delete(table_name, digest)
26
+ client.blob_delete(TABLE_NAME, digest)
28
27
  end
29
28
 
30
29
  context 'file' do
31
30
 
32
31
  it 'should upload a file to the blob table' do
33
32
  f = File.read(file_path)
34
- client.blob_put(table_name, digest, f).should be_true
33
+ client.blob_put(TABLE_NAME, digest, f).should be_true
35
34
  end
36
35
  end
37
36
 
38
37
  context '#string' do
39
- let(:string) {"my crazy"}
40
- let(:digest) {Digest::SHA1.hexdigest(string)}
38
+ let(:string) { "my crazy" }
39
+ let(:digest) { Digest::SHA1.hexdigest(string) }
41
40
 
42
41
  it 'should upload a string to the blob table' do
43
- client.blob_delete(table_name, digest)
44
- client.blob_put table_name, digest, string
42
+ client.blob_delete(TABLE_NAME, digest)
43
+ client.blob_put TABLE_NAME, digest, string
45
44
  end
46
45
  end
47
46
  end
@@ -50,11 +49,11 @@ describe CrateRuby::Client do
50
49
 
51
50
  before do
52
51
  f = File.read(file_path)
53
- client.blob_put(table_name, digest, f)
52
+ client.blob_put(TABLE_NAME, digest, f)
54
53
  end
55
54
 
56
55
  it 'should download a blob' do
57
- data = client.blob_get(table_name, digest)
56
+ data = client.blob_get(TABLE_NAME, digest)
58
57
  data.should_not be_false
59
58
  open(store_location, "wb") { |file|
60
59
  file.write(data)
@@ -62,31 +61,31 @@ describe CrateRuby::Client do
62
61
  end
63
62
 
64
63
  after do
65
- client.blob_delete(table_name, digest)
64
+ client.blob_delete(TABLE_NAME, digest)
66
65
  end
67
66
  end
68
67
 
69
68
  describe '#blob_delete' do
70
69
  before do
71
70
  f = File.read(file_path)
72
- client.blob_put(table_name, digest, f)
71
+ client.blob_put(TABLE_NAME, digest, f)
73
72
  end
74
73
 
75
74
  it 'should delete a blob' do
76
- client.blob_delete(table_name, digest)
75
+ client.blob_delete(TABLE_NAME, digest)
77
76
  end
78
77
  end
79
78
  end
80
79
 
81
80
  describe '#execute' do
82
- let(:table_name) { "post" }
81
+ let(:TABLE_NAME) { "post" }
83
82
 
84
83
  after do
85
- client.execute("drop TABLE #{table_name}").should be_true
84
+ client.execute("drop TABLE #{TABLE_NAME}").should be_true
86
85
  end
87
86
 
88
87
  it 'should create a new table' do
89
- client.execute("CREATE TABLE #{table_name} (id int)").should be_true
88
+ client.execute("CREATE TABLE #{TABLE_NAME} (id int)").should be_true
90
89
  end
91
90
 
92
91
  end
@@ -96,10 +95,54 @@ describe CrateRuby::Client do
96
95
 
97
96
  it 'should use host and ports parameters' do
98
97
  logger = double()
99
- client = CrateRuby::Client.new ["10.0.0.1:5000"],logger: logger
98
+ client = CrateRuby::Client.new ["10.0.0.1:5000"], logger: logger
100
99
  client.instance_variable_get(:@servers).should eq(["10.0.0.1:5000"])
101
100
  end
101
+ end
102
+
103
+ describe '#tables' do
104
+ before do
105
+ client.create_table "posts", id: :integer
106
+ client.create_table "comments", id: :integer
107
+ end
108
+
109
+ after do
110
+ client.drop_table "posts"
111
+ client.drop_table "comments"
112
+ end
113
+
114
+ it 'should return all user tables as an array of string values' do
115
+ client.tables.should eq ['posts', 'comments']
116
+ end
117
+ end
102
118
 
119
+
120
+ describe '#insert' do
121
+ before do
122
+ client.create_table("posts", id: [:string, "primary key"],
123
+ title: :string,
124
+ views: :integer)
125
+ end
126
+
127
+ after do
128
+ client.drop_table "posts"
129
+ end
130
+
131
+ it 'should insert the record' do
132
+ expect do
133
+ client.insert('posts', id: SecureRandom.uuid, title: "Test" )
134
+ sleep(1)
135
+ result_set = client.execute("Select * from posts where title = 'Test'")
136
+ result_set.rowcount.should eq 1
137
+ end.not_to raise_exception
138
+ end
139
+ end
140
+
141
+ describe '#refresh table' do
142
+ it 'should issue the proper refresh statment' do
143
+ client.should_receive(:execute).with("refresh table posts")
144
+ client.refresh_table('posts')
145
+ end
103
146
  end
104
147
 
105
148
  end
@@ -56,6 +56,12 @@ describe ResultSet do
56
56
  end
57
57
  end
58
58
 
59
+ describe '#values' do
60
+ it 'should return all rows as an array of arrays' do
61
+ result_set.values.should eq json_result['rows']
62
+ end
63
+ end
64
+
59
65
  end
60
66
 
61
67
 
data/spec/spec_helper.rb CHANGED
@@ -1 +1,2 @@
1
1
  require_relative '../lib/crate_ruby'
2
+ TEST_PORT = 4209
@@ -0,0 +1,70 @@
1
+ require 'net/http'
2
+ class TestServer
3
+ CRATE_PATH = "~/crate"
4
+ TEST_PORT = 4209
5
+ NAME = "TestCluster"
6
+
7
+
8
+ def initialize(crate_home = nil, port = nil, host = "127.0.0.1")
9
+ @crate_home = crate_home || CRATE_PATH
10
+ @port = port || TEST_PORT
11
+ @host = host
12
+ end
13
+
14
+ def start
15
+ cmd = "sh #{CRATE_PATH}/bin/crate #{start_params}"
16
+ @pid = spawn(cmd, :out => "/tmp/crate_test_server.out", :err => "/tmp/crate_test_server.err")
17
+ Process.detach(@pid)
18
+ puts 'starting'
19
+ time_slept = 0
20
+ while true
21
+ puts "Crate not yet fully available. Waiting since #{time_slept} seconds..." unless alive?
22
+ sleep(2)
23
+ time_slept += 2
24
+ end
25
+ end
26
+
27
+ def stop
28
+ Process.kill("HUP", @pid)
29
+ end
30
+
31
+ private
32
+
33
+
34
+ def crate_exec
35
+ end
36
+
37
+ def crate_config
38
+ end
39
+
40
+ def start_params
41
+ "-Des.index.storage.type=memory " +
42
+ "-Des.node.name=#{NAME} " +
43
+ "-Des.cluster.name=Testing#{@port} " +
44
+ "-Des.http.port=#{@port}-#{@port} " +
45
+ "-Des.network.host=localhost " +
46
+ "-Des.discovery.type=zen " +
47
+ "-Des.discovery.zen.ping.multicast.enabled=false"
48
+ end
49
+
50
+ def alive?
51
+ req = Net::HTTP::Get.new('/')
52
+ resp = Net::HTTP.new(@host, @port)
53
+ begin
54
+ response = resp.start { |http| http.request(req) }
55
+ response.code == "200" ? true : false
56
+ rescue Errno::ECONNREFUSED
57
+ false
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ server = TestServer.new.start *ARGV
64
+
65
+ trap("INT") do
66
+ puts "Script terminated by user."
67
+ server.stop
68
+ puts "Server stopped"
69
+ exit
70
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crate_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christoph Klocker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-09 00:00:00.000000000 Z
11
+ date: 2014-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -74,6 +74,7 @@ files:
74
74
  - spec/crate_ruby/client_spec.rb
75
75
  - spec/crate_ruby/result_set_spec.rb
76
76
  - spec/spec_helper.rb
77
+ - spec/test_server.rb
77
78
  - spec/uploads/get_logo-crate.png
78
79
  - spec/uploads/logo-crate.png
79
80
  - spec/uploads/text.txt
@@ -105,6 +106,7 @@ test_files:
105
106
  - spec/crate_ruby/client_spec.rb
106
107
  - spec/crate_ruby/result_set_spec.rb
107
108
  - spec/spec_helper.rb
109
+ - spec/test_server.rb
108
110
  - spec/uploads/get_logo-crate.png
109
111
  - spec/uploads/logo-crate.png
110
112
  - spec/uploads/text.txt