tarantool 0.2.5 → 0.3.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/Gemfile +14 -12
  2. data/LICENSE +4 -4
  3. data/README.md +15 -9
  4. data/Rakefile +5 -129
  5. data/lib/tarantool/base_record.rb +288 -0
  6. data/lib/tarantool/block_db.rb +135 -0
  7. data/lib/tarantool/callback_db.rb +47 -0
  8. data/lib/tarantool/core-ext.rb +12 -0
  9. data/lib/tarantool/em_db.rb +37 -0
  10. data/lib/tarantool/exceptions.rb +52 -7
  11. data/lib/tarantool/fiber_db.rb +152 -0
  12. data/lib/tarantool/light_record.rb +68 -0
  13. data/lib/tarantool/query.rb +127 -0
  14. data/lib/tarantool/record/select.rb +59 -0
  15. data/lib/tarantool/record.rb +93 -282
  16. data/lib/tarantool/request.rb +351 -52
  17. data/lib/tarantool/response.rb +108 -45
  18. data/lib/tarantool/serializers/bson.rb +2 -2
  19. data/lib/tarantool/serializers.rb +32 -4
  20. data/lib/tarantool/space_array.rb +153 -0
  21. data/lib/tarantool/space_hash.rb +262 -0
  22. data/lib/tarantool/util.rb +182 -0
  23. data/lib/tarantool/version.rb +3 -0
  24. data/lib/tarantool.rb +79 -29
  25. data/test/box.pid +1 -0
  26. data/test/helper.rb +164 -0
  27. data/test/run_all.rb +3 -0
  28. data/test/shared_query.rb +73 -0
  29. data/test/shared_record.rb +474 -0
  30. data/test/shared_space_array.rb +284 -0
  31. data/test/shared_space_hash.rb +239 -0
  32. data/test/tarant/init.lua +22 -0
  33. data/test/tarantool.cfg +62 -0
  34. data/test/tarantool.log +6 -0
  35. data/{spec/tarantool.cfg → test/tarantool_repl.cfg} +11 -5
  36. data/test/test_light_record.rb +48 -0
  37. data/test/test_query_block.rb +6 -0
  38. data/test/test_query_fiber.rb +7 -0
  39. data/test/test_record.rb +88 -0
  40. data/{spec/tarantool/composite_primary_key_spec.rb → test/test_record_composite_pk.rb} +5 -7
  41. data/test/test_space_array_block.rb +6 -0
  42. data/test/test_space_array_callback.rb +255 -0
  43. data/test/test_space_array_callback_nodef.rb +190 -0
  44. data/test/test_space_array_fiber.rb +7 -0
  45. data/test/test_space_hash_block.rb +6 -0
  46. data/test/test_space_hash_fiber.rb +7 -0
  47. metadata +78 -55
  48. data/Gemfile.lock +0 -54
  49. data/examples/em_simple.rb +0 -16
  50. data/examples/record.rb +0 -68
  51. data/examples/simple.rb +0 -13
  52. data/lib/tarantool/requests/call.rb +0 -20
  53. data/lib/tarantool/requests/delete.rb +0 -18
  54. data/lib/tarantool/requests/insert.rb +0 -19
  55. data/lib/tarantool/requests/ping.rb +0 -16
  56. data/lib/tarantool/requests/select.rb +0 -22
  57. data/lib/tarantool/requests/update.rb +0 -35
  58. data/lib/tarantool/requests.rb +0 -19
  59. data/lib/tarantool/serializers/integer.rb +0 -14
  60. data/lib/tarantool/serializers/string.rb +0 -14
  61. data/lib/tarantool/space.rb +0 -39
  62. data/spec/helpers/let.rb +0 -11
  63. data/spec/helpers/truncate.rb +0 -12
  64. data/spec/spec_helper.rb +0 -21
  65. data/spec/tarantool/em_spec.rb +0 -22
  66. data/spec/tarantool/record_spec.rb +0 -316
  67. data/spec/tarantool/request_spec.rb +0 -103
  68. data/tarantool.gemspec +0 -69
data/Gemfile CHANGED
@@ -1,14 +1,16 @@
1
- source "http://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- gem "activemodel"
3
+ group :development do
4
+ gem "debugger"
5
+ end
4
6
 
5
- gem "rr"
6
- gem "yajl-ruby"
7
- gem "bson"
8
- gem "bson_ext"
9
-
10
- gem "ruby-debug19"
11
-
12
- gem "em-synchrony"
13
-
14
- gemspec
7
+ group :test do
8
+ gem "rr"
9
+ gem "activesupport"
10
+ gem "activemodel"
11
+ gem "yajl-ruby"
12
+ gem "bson"
13
+ gem "bson_ext"
14
+ end
15
+ # Specify your gem's dependencies in em-tarantool.gemspec
16
+ gemspec
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
- /*
2
- * Copyright (C) 2011 Mail.RU
3
- *
1
+ /*
2
+ * Copyright (C) 2011-2012 Mail.RU
3
+ *
4
4
  * Redistribution and use in source and binary forms, with or without
5
5
  * modification, are permitted provided that the following conditions
6
6
  * are met:
@@ -21,4 +21,4 @@
21
21
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
22
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
23
  * SUCH DAMAGE.
24
- */
24
+ */
data/README.md CHANGED
@@ -22,7 +22,13 @@ DB = Tarantool.new host: 'locahost', port: 33013
22
22
  space = DB.space 0
23
23
  ```
24
24
 
25
- The driver internals can work in two modes: block via TCPSocket and non block via EventMachine and fibers. By default it uses block mode.
25
+ The driver internals can work in three modes:
26
+ - blocking via TCPSocket
27
+ - callback style via EventMachine
28
+ - EM::Synchrony like via EventMachine and fibers, so that control flow is visually
29
+ blocked, but eventloop is not (see EM::Synchrony)
30
+
31
+ By default it uses block mode.
26
32
 
27
33
 
28
34
  ```ruby
@@ -49,7 +55,7 @@ EM.synchrony do
49
55
  end
50
56
  ```
51
57
 
52
- The driver itself provides ActiveModel API: Callbacks, Validations, Serialization, Dirty.
58
+ The driver itself provides ActiveModel API: Callbacks, Validations, Serialization, Dirty.
53
59
  Type casting is automatic, based on the index type chosen to process the query.
54
60
  For example:
55
61
 
@@ -59,7 +65,7 @@ require 'tarantool/serializers/bson'
59
65
  class User < Tarantool::Record
60
66
  field :login, :string
61
67
  field :name, :string
62
- field :email, :string
68
+ field :email, :string
63
69
  field :apples_count, :integer, default: 0
64
70
  field :info, :bson
65
71
  index :name, :email
@@ -76,16 +82,16 @@ User.create login: 'prepor', email: 'ceo@prepor.ru', name: 'Andrew'
76
82
  User.create login: 'ruden', name: 'Andrew', email: 'rudenkoco@gmail.com'
77
83
 
78
84
  # find by primary key login
79
- User.find 'prepor'
85
+ User.find 'prepor'
80
86
  # first 2 users with name Andrew
81
- User.where(name: 'Andrew').limit(2).all
87
+ User.where(name: 'Andrew').limit(2).all
82
88
  # second user with name Andrew
83
- User.where(name: 'Andrew').offset(1).limit(1).all
89
+ User.where(name: 'Andrew').offset(1).limit(1).all
84
90
  # user with name Andrew and email ceo@prepor.ru
85
91
  User.where(name: 'Andrew', email: 'ceo@prepor.ru').first
86
92
  # raise exception, becouse we can't select query started from not first part of index
87
93
  begin
88
- User.where(email: 'ceo@prepor.ru')
94
+ User.where(email: 'ceo@prepor.ru')
89
95
  rescue Tarantool::ArgumentError => e
90
96
  end
91
97
  # increment field apples_count by one. Its atomic operation via native Tarantool interface
@@ -105,7 +111,7 @@ user.destroy
105
111
  ```
106
112
 
107
113
  When definining a record, field order is important: this is the order of fields
108
- in the tuple stored by Tarantool. By default, the primary key is field 0.
114
+ in the tuple stored by Tarantool. By default, the primary key is field 0.
109
115
 
110
116
  `index` method just mapping to your Tarantool schema, client doesn't modify schema for you.
111
117
 
@@ -117,4 +123,4 @@ in the tuple stored by Tarantool. By default, the primary key is field 0.
117
123
  * admin-socket protocol
118
124
  * safe to add fields to exist model
119
125
  * Hash, Array and lambdas as default values
120
- * timers to response, reconnect strategies
126
+ * timers to response, reconnect strategies
data/Rakefile CHANGED
@@ -1,131 +1,7 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require 'date'
4
-
5
- #############################################################################
6
- #
7
- # Helper functions
8
- #
9
- #############################################################################
10
-
11
- def name
12
- @name ||= Dir['*.gemspec'].first.split('.').first
13
- end
14
-
15
- def version
16
- line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
17
- line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
- end
19
-
20
- def date
21
- Date.today.to_s
22
- end
23
-
24
- def rubyforge_project
25
- name
26
- end
27
-
28
- def gemspec_file
29
- "#{name}.gemspec"
30
- end
31
-
32
- def gem_file
33
- "#{name}-#{version}.gem"
34
- end
35
-
36
- def replace_header(head, header_name)
37
- head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
- end
39
-
40
- #############################################################################
41
- #
42
- # Standard tasks
43
- #
44
- #############################################################################
45
-
46
-
47
- task :default => :spec
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
48
3
  require 'rake/testtask'
49
- Rake::TestTask.new(:spec) do |t|
50
- t.libs << 'spec'
51
- t.pattern = 'spec/**/*_spec.rb'
52
- t.verbose = false
53
- end
54
-
55
- desc "Generate RCov test coverage and open in your browser"
56
- task :coverage do
57
- require 'rcov'
58
- sh "rm -fr coverage"
59
- sh "rcov test/test_*.rb"
60
- sh "open coverage/index.html"
61
- end
62
-
63
- desc "Open an irb session preloaded with this library"
64
- task :console do
65
- sh "irb -rubygems -r ./lib/#{name}.rb"
66
- end
67
-
68
-
69
- #############################################################################
70
- #
71
- # Packaging tasks
72
- #
73
- #############################################################################
74
-
75
- desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
76
- task :release => :build do
77
- unless `git branch` =~ /^\* master$/
78
- puts "You must be on the master branch to release!"
79
- exit!
80
- end
81
- sh "git commit --allow-empty -m 'Release #{version}'"
82
- sh "git tag v#{version}"
83
- sh "git push origin master"
84
- sh "git push origin v#{version}"
85
- sh "gem push pkg/#{name}-#{version}.gem"
86
- end
87
-
88
- desc "Build #{gem_file} into the pkg directory"
89
- task :build => :gemspec do
90
- sh "mkdir -p pkg"
91
- sh "gem build #{gemspec_file}"
92
- sh "mv #{gem_file} pkg"
93
- end
94
-
95
- desc "Generate #{gemspec_file}"
96
- task :gemspec => :validate do
97
- # read spec file and split out manifest section
98
- spec = File.read(gemspec_file)
99
- head, manifest, tail = spec.split(" # = MANIFEST =\n")
100
-
101
- # replace name version and date
102
- replace_header(head, :name)
103
- replace_header(head, :version)
104
- replace_header(head, :date)
105
- #comment this out if your rubyforge_project has a different name
106
- replace_header(head, :rubyforge_project)
107
-
108
- # determine file list from git ls-files
109
- files = `git ls-files`.
110
- split("\n").
111
- sort.
112
- reject { |file| file =~ /^\./ }.
113
- reject { |file| file =~ /^(rdoc|pkg)/ }.
114
- map { |file| " #{file}" }.
115
- join("\n")
116
-
117
- # piece file back together and write
118
- manifest = " s.files = %w[\n#{files}\n ]\n"
119
- spec = [head, manifest, tail].join(" # = MANIFEST =\n")
120
- File.open(gemspec_file, 'w') { |io| io.write(spec) }
121
- puts "Updated #{gemspec_file}"
4
+ Rake::TestTask.new do |i|
5
+ i.options = '-v'
6
+ i.verbose = true
122
7
  end
123
-
124
- desc "Validate #{gemspec_file}"
125
- task :validate do
126
- libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
127
- unless Dir['VERSION*'].empty?
128
- puts "A `VERSION` file at root level violates Gem best practices."
129
- exit!
130
- end
131
- end
@@ -0,0 +1,288 @@
1
+ require 'tarantool'
2
+ require 'tarantool/record/select'
3
+ require 'active_support/core_ext/class/attribute'
4
+
5
+ module Tarantool
6
+ class RecordError < StandardError; end
7
+ class UpdateNewRecord < RecordError; end
8
+
9
+ class BaseRecord
10
+ class_attribute :fields, instance_reader: false, instance_writer: false
11
+ self.fields = {}.freeze
12
+
13
+ class_attribute :default_values, instance_reader: false, instance_writer: false
14
+ self.default_values = {}.freeze
15
+
16
+ class_attribute :indexes, instance_reader: false, instance_writer: false
17
+ self.indexes = [].freeze
18
+
19
+ class_attribute :space_no, instance_reader: false, instance_writer: false
20
+ class_attribute :tarantool, instance_reader: false, instance_writer: false
21
+
22
+ class << self
23
+ alias set_space_no space_no=
24
+ alias set_tarantool tarantool=
25
+ end
26
+
27
+ module ClassMethods
28
+ def field(name, type, params = {})
29
+ type = Serializers.check_type(type)
30
+
31
+ raise ArgumentError, "_tail should be last declaration" if fields.include?(:_tail)
32
+ self.fields = fields.merge(name => type)
33
+ index name if indexes.empty?
34
+
35
+ if params[:default]
36
+ self.default_values = default_values.merge name => params[:default]
37
+ end
38
+
39
+ define_field_accessor(name, type)
40
+ end
41
+
42
+ def _tail(*types)
43
+ types = types.map{|type| Serializers.check_type(type)}
44
+
45
+ raise ArgumentError, "double _tail declaration" if fields.include?(:_tail)
46
+ self.fields = fields.merge(:_tail => types)
47
+
48
+ define_field_accessor(:_tail, types)
49
+ end
50
+
51
+ def index(*fields)
52
+ options = Hash === fields.last ? fields.pop : {}
53
+ if options[:primary]
54
+ self.indexes = indexes.dup.tap{|ind| ind[0] = fields}
55
+ else
56
+ self.indexes += [fields]
57
+ end
58
+ end
59
+
60
+ def primary_index
61
+ indexes[0]
62
+ end
63
+
64
+ def space
65
+ @space ||= begin
66
+ tarantool.space_hash(space_no, fields.dup, keys: indexes)
67
+ end
68
+ end
69
+
70
+ # space that will return records as results for calls
71
+ # it is useful, if you wish to use callback interface
72
+ def auto_space
73
+ @auto_space ||= begin
74
+ space.with_translator(method(:from_fetched))
75
+ end
76
+ end
77
+
78
+ def by_pk(pk)
79
+ if Hash === (res = space.by_pk(pk))
80
+ from_fetched(res)
81
+ end
82
+ end
83
+
84
+ def by_pks(pks)
85
+ space.all_by_pks(pks).map{|hash| from_fetched(hash)}
86
+ end
87
+
88
+ def find(*args)
89
+ if args.size == 1
90
+ by_pk(args[0])
91
+ else
92
+ by_pks(args)
93
+ end
94
+ end
95
+
96
+ def first(cond)
97
+ if Hash === cond
98
+ if Hash === (res = space.first(cond))
99
+ from_fetched(res)
100
+ end
101
+ else
102
+ by_pk(cond)
103
+ end
104
+ end
105
+
106
+ def all(cond, opts={})
107
+ res = space.all(cond, opts)
108
+ res.map!{|hash| from_fetched(hash)}
109
+ res
110
+ end
111
+
112
+ def select(cond=nil, opts={})
113
+ cond.nil? ? Select.new(self) : all(cond, opts)
114
+ end
115
+
116
+ def create(attributes = {})
117
+ r = new(attributes)
118
+ r.save
119
+ r
120
+ end
121
+
122
+ # Call stored procedure without returning tuples. By default, it prepends
123
+ # +space_no+ to arguments. To avoid prepending, set +space_no: nil+ in options.
124
+ #
125
+ # MyRecord.call('box.select_range', offset, limit)
126
+ # MyRecord.call('myfunction', arg1, arg2, space_no: nil)
127
+ #
128
+ def invoke(proc_name, *args)
129
+ opts = Hash === args.last ? args.pop : {}
130
+ space.invoke(proc_name, args, opts)
131
+ end
132
+
133
+ # Call stored procedure. By default, it prepends +space_no+ to arguments.
134
+ # To avoid prepending, set +space_no: nil+ in options.
135
+ #
136
+ # MyRecord.call('box.select_range', offset, limit)
137
+ # MyRecord.call('myfunction', arg1, arg2, space_no: nil)
138
+ #
139
+ # You could recieve arbitarry arrays or hashes instead of instances of
140
+ # record, if you pass +:returns+ argument. See documentation for +SpaceHash+
141
+ # for this.
142
+ def call(proc_name, *args)
143
+ opts = Hash === args.last ? args.pop : {}
144
+ res = space.call(proc_name, args, opts)
145
+ if Array === res && !opts[:returns]
146
+ res.map{|hash| from_fetched(hash) }
147
+ else
148
+ res
149
+ end
150
+ end
151
+
152
+ def from_fetched(hash)
153
+ hash && allocate.__fetched(hash)
154
+ end
155
+
156
+ def insert(hash, ret_tuple = false)
157
+ hash = default_values.merge(hash)
158
+ if ret_tuple
159
+ from_fetched space.insert(hash, return_tuple: true)
160
+ else
161
+ space.insert(hash)
162
+ end
163
+ end
164
+
165
+ def replace(hash, ret_tuple = false)
166
+ hash = default_values.merge(hash)
167
+ if ret_tuple
168
+ from_fetched space.replace(hash, return_tuple: true)
169
+ else
170
+ space.replace(hash)
171
+ end
172
+ end
173
+
174
+ def update(pk, ops, ret_tuple=false)
175
+ if ret_tuple
176
+ from_fetched space.update(pk, ops, return_tuple: true)
177
+ else
178
+ space.update(pk, ops)
179
+ end
180
+ end
181
+
182
+ def delete(pk, ret_tuple=false)
183
+ if ret_tuple
184
+ from_fetched space.delete(pk, return_tuple: true)
185
+ else
186
+ space.delete(pk)
187
+ end
188
+ end
189
+
190
+ %w{where limit offset}.each do |meth|
191
+ class_eval <<-"EOF", __FILE__, __LINE__
192
+ def #{meth}(arg)
193
+ select.#{meth}(arg)
194
+ end
195
+ EOF
196
+ end
197
+ end
198
+ extend ClassMethods
199
+
200
+ module InstanceMethods
201
+ attr_accessor :__new_record
202
+ attr_reader :attributes
203
+ alias new_record __new_record
204
+ alias new_record? new_record
205
+
206
+ def new_record!
207
+ @__new_record = true
208
+ self
209
+ end
210
+
211
+ def old_record!
212
+ @__new_record = false
213
+ self
214
+ end
215
+
216
+ def set_attributes(attributes)
217
+ attributes.each do |k, v|
218
+ send("#{k}=", v)
219
+ end
220
+ end
221
+
222
+ def _tail
223
+ @attributes[:_tail]
224
+ end
225
+
226
+ def _tail=(v)
227
+ @attributes[:_tail] = v
228
+ end
229
+
230
+ def update_attributes(attributes)
231
+ set_attributes(attributes)
232
+ save
233
+ end
234
+
235
+ def id
236
+ (primary = self.class.primary_index).size == 1 ?
237
+ @attributes[primary[0]] :
238
+ @attributes.values_at(*primary)
239
+ end
240
+
241
+ def space
242
+ self.class.space
243
+ end
244
+
245
+ def auto_space
246
+ self.class.space
247
+ end
248
+
249
+ def reload
250
+ if hash = space.by_pk(id)
251
+ @__new_record = false
252
+ @attributes = hash
253
+ self
254
+ else
255
+ _raise_doesnt_exists("reload")
256
+ end
257
+ end
258
+
259
+ def ==(other)
260
+ equal?(other) || (other.class == self.class && id == other.id)
261
+ end
262
+
263
+ # update record in db first, reload it then
264
+ #
265
+ # record.update({:state => 'sleep', :sleep_count => [:+, 1]})
266
+ # record.update([[:state, 'sleep'], [:sleep_count, :+, 1]])
267
+ def update(ops)
268
+ raise UpdateNewRecord, "Could not call update on new record" if @__new_record
269
+ unless new_attrs = space.update(id, ops, return_tuple: true)
270
+ _raise_doesnt_exists
271
+ end
272
+ @attributes = new_attrs
273
+
274
+ self
275
+ end
276
+
277
+ def increment(field, by = 1)
278
+ update([[field.to_sym, :+, by]])
279
+ end
280
+
281
+ def _raise_doesnt_exists(action = "update")
282
+ raise TupleDoesntExists.new(0x3102, "Record which you wish to #{action}, doesn't exists")
283
+ end
284
+ end
285
+ include InstanceMethods
286
+
287
+ end
288
+ end
@@ -0,0 +1,135 @@
1
+ module Tarantool
2
+ class BlockDB < DB
3
+ def establish_connection
4
+ @connection = IProto.get_connection(@host, @port, :block)
5
+ end
6
+
7
+ def close_connection
8
+ @connection.close
9
+ end
10
+
11
+ def _send_request(request_type, body, cb)
12
+ cb.call @connection.send_request(request_type, body)
13
+ end
14
+
15
+ module CommonSpaceBlockingMethods
16
+ def _block_cb
17
+ @_block_cb ||= method(:_raise_or_return)
18
+ end
19
+
20
+ def all_by_pks(pks, opts={})
21
+ all_by_pks_cb(pks, _block_cb, opts)
22
+ end
23
+
24
+ def by_pk(pk)
25
+ by_pk_cb(pk, _block_cb)
26
+ end
27
+
28
+ def insert(tuple, opts={})
29
+ insert_cb(tuple, _block_cb, opts)
30
+ end
31
+
32
+ def replace(tuple, opts={})
33
+ replace_cb(tuple, _block_cb, opts)
34
+ end
35
+
36
+ def update(pk, operations, opts={})
37
+ update_cb(pk, operations, _block_cb, opts)
38
+ end
39
+
40
+ def delete(pk, opts={})
41
+ delete_cb(pk, _block_cb, opts)
42
+ end
43
+
44
+ def invoke(func_name, values = [], opts = {})
45
+ invoke_cb(func_name, values, _block_cb, opts)
46
+ end
47
+
48
+ def call(func_name, values = [], opts = {})
49
+ call_cb(func_name, values, _block_cb, opts)
50
+ end
51
+
52
+ def ping
53
+ ping_cb(_block_cb)
54
+ end
55
+ end
56
+
57
+ class SpaceArray < ::Tarantool::SpaceArray
58
+ include CommonSpaceBlockingMethods
59
+
60
+ def all_by_key(index_no, key, opts={})
61
+ all_by_key_cb(index_no, key, _block_cb, opts)
62
+ end
63
+
64
+ def first_by_key(index_no, key)
65
+ first_by_key_cb(index_no, key, _block_cb)
66
+ end
67
+
68
+ def all_by_keys(index_no, keys, opts={})
69
+ all_by_keys_cb(index_no, keys, _block_cb, opts)
70
+ end
71
+
72
+ def select(index_no, keys, offset=0, limit=-1)
73
+ select_cb(index_no, keys, offset, limit, _block_cb)
74
+ end
75
+ end
76
+
77
+ class SpaceHash < ::Tarantool::SpaceHash
78
+ include CommonSpaceBlockingMethods
79
+
80
+ def all(keys, opts = {})
81
+ all_cb(keys, _block_cb, opts)
82
+ end
83
+
84
+ def first(key)
85
+ first_cb(key, _block_cb)
86
+ end
87
+
88
+ def select(keys, offset=0, limit=-1)
89
+ select_cb(keys, offset, limit, _block_cb)
90
+ end
91
+ end
92
+
93
+ class Query < ::Tarantool::Query
94
+ def select(space_no, index_no, keys, offset, limit, opts={})
95
+ select_cb(space_no, index_no, keys, offset, limit, _block_cb, opts)
96
+ end
97
+
98
+ def all(space_no, index_no, keys, opts={})
99
+ all_cb(space_no, index_no, keys, _block_cb, opts)
100
+ end
101
+
102
+ def first(space_no, index_no, key, opts={})
103
+ first_cb(space_no, index_no, key, _block_cb, opts)
104
+ end
105
+
106
+ def insert(space_no, tuple, opts={})
107
+ insert_cb(space_no, tuple, _block_cb, opts)
108
+ end
109
+
110
+ def replace(space_no, tuple, opts={})
111
+ replace_cb(space_no, tuple, _block_cb, opts)
112
+ end
113
+
114
+ def update(space_no, pk, operation, opts={})
115
+ update_cb(space_no, pk, operation, _block_cb, opts)
116
+ end
117
+
118
+ def delete(space_no, pk, opts={})
119
+ delete_cb(space_no, pk, _block_cb, opts)
120
+ end
121
+
122
+ def invoke(func_name, values, opts={})
123
+ invoke_cb(func_name, values, _block_cb, opts)
124
+ end
125
+
126
+ def call(func_name, values, opts={})
127
+ call_cb(func_name, values, _block_cb, opts)
128
+ end
129
+
130
+ def ping
131
+ ping_cb(_block_cb)
132
+ end
133
+ end
134
+ end
135
+ end