activetokyocabinet 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -4,11 +4,11 @@ Copyright (c) 2010 SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
4
4
 
5
5
  == Description
6
6
 
7
- ActiveTokyoCabinet is a library for using TokyoCabinet under ActiveRecord.
7
+ ActiveTokyoCabinet is a library for using Tokyo(Cabinet|Tyrant) under ActiveRecord.
8
8
 
9
- ActiveTokyoCabinet depend on TokyoCabinet.
9
+ ActiveTokyoCabinet depend on Tokyo(Cabinet|Tyrant).
10
10
 
11
- see http://1978th.net/tokyocabinet/ .
11
+ see http://1978th.net/tokyocabinet/ , http://1978th.net/tokyotyrant/
12
12
 
13
13
  == Project Page
14
14
 
@@ -16,15 +16,23 @@ http://rubyforge.org/projects/activetokyocabi
16
16
 
17
17
  == Install
18
18
 
19
- gem install zipruby
19
+ gem install activetokyocabinet
20
+
21
+ see http://gemcutter.org/gems/activetokyocabinet
20
22
 
21
23
  == Example
22
24
  === database.yml
23
-
25
+ # TokyoCabinet
24
26
  development:
25
27
  adapter: tokyocabinet
26
28
  database: path_of_database_directory
27
29
  # ~~~~~~~~~
30
+ # TokyoCabinet
31
+ development:
32
+ adapter: tokyotyrant
33
+ database:
34
+ hellos: { host: localhost, port: 1978 }
35
+ tests: { host: localhost, port: 1979 }
28
36
 
29
37
  === Model
30
38
 
@@ -41,32 +49,37 @@ gem install zipruby
41
49
 
42
50
  class HelloController < ApplicationController
43
51
  def index
52
+ hello_id = nil
53
+
44
54
  (20..35).each do |i|
45
55
  hello = Hello.new
46
56
  hello.name = 'yamada'
47
- hello.age = 20
57
+ hello.age = i
48
58
  hello.save!
59
+ hello_id = hello.id
49
60
  end
50
61
 
51
62
  p Hello.find(:all,
52
63
  :conditions => ["name = ? and age > ?", "yamada", 25],
53
64
  :order => 'age desc', :limit => 5, :offset => 3)
54
65
 
55
- hello = Hello.find(1)
56
- hello.name = 'sato'
66
+ hello = Hello.find(hello_id)
67
+ hello.name = 'yamashita'
57
68
  hello.save!
58
69
 
59
- p Hello.find(:first, :conditions => ["name = ?", "tanaka"])
70
+ p Hello.find(:first, :conditions => ["name = ?", "yamashita"])
60
71
 
61
- hello = Hello.find(2)
72
+ hello = Hello.find(hello_id)
62
73
  hello.destroy
63
74
 
75
+ p Hello.find(:first, :conditions => ["name = ?", "yamashita"])
76
+
64
77
  p Hello.find(:all)
65
78
 
66
79
  Hello.delete_all(["name = ? and age <= ?", "yamada", 30])
67
80
 
68
81
  p Hello.find(:all)
69
-
82
+
70
83
  render :text => 'hello'
71
84
  end
72
85
  end
@@ -0,0 +1,157 @@
1
+ require 'active_record/connection_adapters/abstract_adapter'
2
+ require 'active_tokyocabinet/tdb'
3
+ require 'active_tokyocabinet/sqlparser.tab'
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ class AbstractTokyoCabinetAdapter < AbstractAdapter
8
+ def initialize(connection, logger, query_klass)
9
+ super(connection, logger)
10
+ @query_klass = query_klass
11
+ end
12
+
13
+ def supports_count_distinct?
14
+ false
15
+ end
16
+
17
+ def select(sql, name = nil)
18
+ rows = []
19
+
20
+ log(sql, name) do
21
+ parsed_sql = ActiveTokyoCabinet::SQLParser.new(sql).parse
22
+
23
+ tdbopen(parsed_sql) do |tdb|
24
+ select_list = parsed_sql[:select_list]
25
+
26
+ rkeys(tdb, parsed_sql).each do |rkey|
27
+ rcols = tdb.get(rkey)
28
+ next if rcols.nil?
29
+
30
+ unless select_list.nil? or select_list.empty?
31
+ rcols = select_list.each {|k| r[k] = rcols[k] }
32
+ end
33
+
34
+ rcols['id'] = rkey
35
+ rows << rcols
36
+ end
37
+ end
38
+
39
+ if (count = parsed_sql[:count])
40
+ rows = [{count => rows.length}]
41
+ end
42
+ end
43
+
44
+ return rows
45
+ end
46
+
47
+ def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
48
+ pkey = nil
49
+
50
+ log(sql, name) do
51
+ parsed_sql = ActiveTokyoCabinet::SQLParser.new(sql).parse
52
+
53
+ tdbopen(parsed_sql) do |tdb|
54
+ pkey = tdb.genuid
55
+ keys = parsed_sql[:column_list]
56
+ vals = parsed_sql[:value_list]
57
+ cols = {}
58
+
59
+ keys.zip(vals).each do |k, v|
60
+ cols[k] = v.to_s
61
+ end
62
+
63
+ unless tdb.put(pkey, cols)
64
+ ecode = tdb.ecode
65
+ raise '%s: %s' % [tdb.errmsg(ecode), sql]
66
+ end
67
+ end
68
+ end
69
+ return pkey
70
+ end
71
+
72
+ def update_sql(sql, name = nil)
73
+ rownum = 0
74
+
75
+ log(sql, name) do
76
+ parsed_sql = ActiveTokyoCabinet::SQLParser.new(sql).parse
77
+
78
+ tdbopen(parsed_sql) do |tdb|
79
+ set_clause_list = parsed_sql[:set_clause_list]
80
+
81
+ rkeys(tdb, parsed_sql).each do |rkey|
82
+ rcols = tdb.get(rkey)
83
+
84
+ set_clause_list.each do |k, v|
85
+ rcols[k] = v.to_s
86
+ end
87
+
88
+ rownum += 1
89
+
90
+ unless tdb.put(rkey, rcols)
91
+ ecode = tdb.ecode
92
+ raise '%s: %s' % [tdb.errmsg(ecode), sql]
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ return rownum
99
+ end
100
+
101
+ def delete_sql(sql, name = nil)
102
+ rownum = 0
103
+
104
+ log(sql, name) do
105
+ parsed_sql = ActiveTokyoCabinet::SQLParser.new(sql).parse
106
+
107
+ tdbopen(parsed_sql) do |tdb|
108
+ rkeys(tdb, parsed_sql)
109
+ set_clause_list = parsed_sql[:set_clause_list]
110
+
111
+ rkeys(tdb, parsed_sql).each do |rkey|
112
+ rownum += 1
113
+
114
+ unless tdb.out(rkey)
115
+ ecode = tdb.ecode
116
+ raise '%s: %s' % [tdb.errmsg(ecode), sql]
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ return rownum
123
+ end
124
+
125
+ def rkeys(tdb, parsed_sql)
126
+ condition, order, limit, offset = parsed_sql.values_at(:condition, :order, :limit, :offset)
127
+ condition ||= []
128
+
129
+ unless condition.kind_of?(Array) and condition.all? {|i| i.kind_of?(Hash) }
130
+ return [parsed_sql[:condition]].flatten
131
+ end
132
+
133
+ qry = @query_klass::new(tdb)
134
+
135
+ condition.each do |cond|
136
+ name, op, expr = cond.values_at(:name, :op, :expr)
137
+ op = @query_klass.const_get(op)
138
+ expr = expr.kind_of?(Array) ? expr.join(' ') : expr.to_s
139
+ qry.addcond(name, op, expr)
140
+ end
141
+
142
+ if order
143
+ name, type = order.values_at(:name, :type)
144
+ type = @query_klass.const_get(type)
145
+ qry.setorder(name, type)
146
+ end
147
+
148
+ if limit or offset
149
+ qry.setlimit(limit || 0, offset || 0)
150
+ end
151
+
152
+ return qry.search
153
+ end
154
+ private :rkeys
155
+ end
156
+ end
157
+ end
@@ -1,235 +1,65 @@
1
- require 'active_record/connection_adapters/abstract_adapter'
2
- require 'tokyocabinet'
3
- require 'active_tokyocabinet/tdb'
4
- require 'active_tokyocabinet/sqlparser.tab'
5
-
6
- module ActiveRecord
7
- class Base
8
- def self.tokyocabinet_connection(config)
9
- unless config[:database]
10
- raise ArgumentError, "No database file specified. Missing argument: database"
11
- end
12
-
13
- if Object.const_defined?(:RAILS_ROOT)
14
- config[:database] = File.expand_path(config[:database], RAILS_ROOT)
15
- end
16
-
17
- ConnectionAdapters::TokyoCabinetAdapter.new(nil, logger, config)
18
- end
19
- end
20
-
21
- module ConnectionAdapters
22
- class TokyoCabinetAdapter < AbstractAdapter
23
- def initialize(connection, logger, config)
24
- super(connection, logger)
25
- @config = config
26
- end
27
-
28
- def table_exists?(table_name)
29
- path = tdbpath(table_name)
30
- File.exist?(path)
31
- end
32
-
33
- def select(sql, name = nil)
34
- rows = []
35
-
36
- log(sql, name) do
37
- parsed_sql = ActiveTokyoCabinet::SQLParser.new(sql).parse
38
-
39
- tdbopen(parsed_sql[:table], TokyoCabinet::TDB::OREADER) do |tdb|
40
- if (qry = tdbqry(tdb, parsed_sql))
41
- rkeys = qry.search
42
- else
43
- rkeys = [parsed_sql[:condition]].flatten
44
- end
45
-
46
- select_list = parsed_sql[:select_list]
47
-
48
- rkeys.each do |rkey|
49
- rcols = tdb.get(rkey)
50
- next if rcols.nil?
51
-
52
- unless select_list.nil? or select_list.empty?
53
- rcols = select_list.each {|k| r[k] = rcols[k] }
54
- end
55
-
56
- rcols['id'] = rkey
57
- rows << rcols
58
- end
59
- end
60
-
61
- if (count = parsed_sql[:count])
62
- rows = [{count => rows.length}]
63
- end
64
- end
65
-
66
- return rows
67
- end
68
-
69
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
70
- pkey = nil
71
-
72
- log(sql, name) do
73
- parsed_sql = ActiveTokyoCabinet::SQLParser.new(sql).parse
74
-
75
- tdbopen(parsed_sql[:table], TokyoCabinet::TDB::OWRITER) do |tdb|
76
- pkey = tdb.genuid
77
- keys = parsed_sql[:column_list]
78
- vals = parsed_sql[:value_list]
79
- cols = {}
80
-
81
- keys.zip(vals).each do |k, v|
82
- cols[k] = v.to_s
83
- end
84
-
85
- unless tdb.put(pkey, cols)
86
- ecode = tdb.ecode
87
- raise '%s: %s' % [tdb.errmsg(ecode), sql]
88
- end
89
- end
90
- end
91
- return pkey
92
- end
93
-
94
- def update_sql(sql, name = nil)
95
- rownum = 0
96
-
97
- log(sql, name) do
98
- parsed_sql = ActiveTokyoCabinet::SQLParser.new(sql).parse
99
-
100
- tdbopen(parsed_sql[:table], TokyoCabinet::TDB::OWRITER) do |tdb|
101
- set_clause_list = parsed_sql[:set_clause_list]
102
-
103
- if (qry = tdbqry(tdb, parsed_sql))
104
- r = qry.proc do |pkey, cols|
105
- set_clause_list.each do |k, v|
106
- cols[k] = v.to_s
107
- end
108
-
109
- rownum += 1
110
- TokyoCabinet::TDBQRY::QPPUT
111
- end
112
-
113
- unless r
114
- ecode = tdb.ecode
115
- raise '%s: %s' % [tdb.errmsg(ecode), sql]
116
- end
117
- else
118
- [parsed_sql[:condition]].flatten.each do |rkey|
119
- rcols = tdb.get(rkey)
120
-
121
- set_clause_list.each do |k, v|
122
- rcols[k] = v.to_s
123
- end
124
-
125
- rownum += 1
126
-
127
- unless tdb.put(rkey, rcols)
128
- ecode = tdb.ecode
129
- raise '%s: %s' % [tdb.errmsg(ecode), sql]
130
- end
131
- end
132
- end
133
- end
134
- end
135
-
136
- return rownum
137
- end
138
-
139
- def delete_sql(sql, name = nil) #:nodoc:
140
- rownum = 0
141
-
142
- log(sql, name) do
143
- parsed_sql = ActiveTokyoCabinet::SQLParser.new(sql).parse
144
-
145
- tdbopen(parsed_sql[:table], TokyoCabinet::TDB::OWRITER) do |tdb|
146
- set_clause_list = parsed_sql[:set_clause_list]
147
-
148
- if (qry = tdbqry(tdb, parsed_sql))
149
- r = qry.proc do |pkey, cols|
150
- rownum += 1
151
- TokyoCabinet::TDBQRY::QPOUT
152
- end
153
-
154
- unless r
155
- ecode = tdb.ecode
156
- raise '%s: %s' % [tdb.errmsg(ecode), sql]
157
- end
158
- else
159
- [parsed_sql[:condition]].flatten.each do |rkey|
160
- rownum += 1
161
-
162
- unless tdb.out(rkey)
163
- ecode = tdb.ecode
164
- raise '%s: %s' % [tdb.errmsg(ecode), sql]
165
- end
166
- end
167
- end
168
- end
169
- end
170
-
171
- return rownum
172
- end
173
-
174
- def tdbopen(table_name, omode)
175
- tdb = TokyoCabinet::TDB::new
176
- path = tdbpath(table_name)
177
-
178
- unless File.exist?(path)
179
- omode = TokyoCabinet::TDB::OWRITER | TokyoCabinet::TDB::OCREAT
180
- end
181
-
182
- unless tdb.open(path, omode)
183
- ecode = tdb.ecode
184
- raise "%s: %s" % [tdb.errmsg(ecode), path]
185
- end
186
-
187
- begin
188
- yield(tdb)
189
- ensure
190
- unless tdb.close
191
- ecode = tdb.ecode
192
- raise tdb.errmsg(ecode)
193
- end
194
- end
195
- end
196
- private :tdbopen
197
-
198
- def tdbqry(tdb, parsed_sql)
199
- condition, order, limit, offset = parsed_sql.values_at(:condition, :order, :limit, :offset)
200
- condition ||= []
201
-
202
- unless condition.kind_of?(Array) and condition.all? {|i| i.kind_of?(Hash) }
203
- return nil
204
- end
205
-
206
- qry = TokyoCabinet::TDBQRY::new(tdb)
207
-
208
- condition.each do |cond|
209
- name, op, expr = cond.values_at(:name, :op, :expr)
210
- op = TokyoCabinet::TDBQRY.const_get(op)
211
- expr = expr.kind_of?(Array) ? expr.join(' ') : expr.to_s
212
- qry.addcond(name, op, expr)
213
- end
214
-
215
- if order
216
- name, type = order.values_at(:name, :type)
217
- type = TokyoCabinet::TDBQRY.const_get(type)
218
- qry.setorder(name, type)
219
- end
220
-
221
- if limit or offset
222
- qry.setlimit(limit || 0, offset || 0)
223
- end
224
-
225
- return qry
226
- end
227
- private :tdbqry
228
-
229
- def tdbpath(table_name)
230
- File.join(@config[:database], table_name + ".tct")
231
- end
232
- private :tdbpath
233
- end
234
- end
235
- end
1
+ require 'active_record/connection_adapters/abstract_tokyocabinet_adapter'
2
+ require 'tokyocabinet'
3
+
4
+ module ActiveRecord
5
+ class Base
6
+ def self.tokyocabinet_connection(config)
7
+ unless config[:database]
8
+ raise ArgumentError, "No database file specified. Missing argument: database"
9
+ end
10
+
11
+ if Object.const_defined?(:RAILS_ROOT)
12
+ config[:database] = File.expand_path(config[:database], RAILS_ROOT)
13
+ end
14
+
15
+ ConnectionAdapters::TokyoCabinetAdapter.new(nil, logger, config)
16
+ end
17
+ end
18
+
19
+ module ConnectionAdapters
20
+ class TokyoCabinetAdapter < AbstractTokyoCabinetAdapter
21
+ def initialize(connection, logger, config)
22
+ super(connection, logger, TokyoCabinet::TDBQRY)
23
+ @config = config
24
+ end
25
+
26
+ def table_exists?(table_name)
27
+ path = tdbpath(table_name)
28
+ File.exist?(path)
29
+ end
30
+
31
+ def tdbopen(parsed_sql)
32
+ table_name = parsed_sql[:table]
33
+ path = tdbpath(table_name)
34
+
35
+ if File.exist?(path) and parsed_sql[:command] == :select
36
+ omode = TokyoCabinet::TDB::OREADER
37
+ else
38
+ omode = TokyoCabinet::TDB::OWRITER | TokyoCabinet::TDB::OCREAT
39
+ end
40
+
41
+ tdb = TokyoCabinet::TDB::new
42
+
43
+ unless tdb.open(path, omode)
44
+ ecode = tdb.ecode
45
+ raise "%s: %s" % [tdb.errmsg(ecode), path]
46
+ end
47
+
48
+ begin
49
+ yield(tdb)
50
+ ensure
51
+ unless tdb.close
52
+ ecode = tdb.ecode
53
+ raise tdb.errmsg(ecode)
54
+ end
55
+ end
56
+ end
57
+ private :tdbopen
58
+
59
+ def tdbpath(table_name)
60
+ File.join(@config[:database], table_name + ".tct")
61
+ end
62
+ private :tdbpath
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,63 @@
1
+ require 'active_record/connection_adapters/abstract_tokyocabinet_adapter'
2
+ require 'tokyotyrant'
3
+
4
+ module ActiveRecord
5
+ class Base
6
+ def self.tokyotyrant_connection(config)
7
+ unless config[:database]
8
+ raise ArgumentError, "No database file specified. Missing argument: database"
9
+ end
10
+
11
+ ConnectionAdapters::TokyoTyrantAdapter.new({}, logger, config)
12
+ end
13
+ end
14
+
15
+ module ConnectionAdapters
16
+ class TokyoTyrantAdapter < AbstractTokyoCabinetAdapter
17
+ def initialize(connection, logger, config)
18
+ super(connection, logger, TokyoTyrant::RDBQRY)
19
+ @database = {}
20
+
21
+ config.fetch(:database).map do |table_name, attribute|
22
+ @database[table_name] = {
23
+ :host => attribute.fetch('host').to_s,
24
+ :port => attribute.fetch('port', 0).to_i,
25
+ :timeout => attribute.fetch('timeout', 0).to_i,
26
+ }
27
+ end
28
+ end
29
+
30
+ def table_exists?(table_name)
31
+ @database.has_key?(table_name)
32
+ end
33
+
34
+ def disconnect!
35
+ super
36
+
37
+ @connection.keys.each do |table_name|
38
+ conn = @connection[table_name]
39
+ conn.close
40
+ @connection.delete(table_name)
41
+ end
42
+ end
43
+
44
+ def tdbopen(parsed_sql)
45
+ table_name = parsed_sql[:table]
46
+
47
+ unless (tdb = @connection[table_name])
48
+ host, port, timeout = @database.fetch(table_name).values_at(:host, :port, :timeout)
49
+ tdb = TokyoTyrant::RDBTBL::new
50
+
51
+ unless tdb.open(host, port, timeout)
52
+ ecode = tdb.ecode
53
+ raise "%s: %s" % [tdb.errmsg(ecode), path]
54
+ end
55
+ end
56
+
57
+ yield(tdb)
58
+ @connection[table_name] = tdb
59
+ end
60
+ private :tdbopen
61
+ end
62
+ end
63
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activetokyocabinet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - winebarrel
@@ -13,17 +13,7 @@ date: 2010-01-06 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: rails
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: tokyocabinet
16
+ name: activerecord
27
17
  type: :runtime
28
18
  version_requirement:
29
19
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,6 +32,8 @@ extra_rdoc_files:
42
32
  - README
43
33
  files:
44
34
  - lib/active_record/connection_adapters/tokyocabinet_adapter.rb
35
+ - lib/active_record/connection_adapters/abstract_tokyocabinet_adapter.rb
36
+ - lib/active_record/connection_adapters/tokyotyrant_adapter.rb
45
37
  - lib/active_tokyocabinet/tdb.rb
46
38
  - lib/active_tokyocabinet/sqlparser.y
47
39
  - lib/active_tokyocabinet/sqlparser.tab.rb
@@ -53,7 +45,7 @@ licenses: []
53
45
  post_install_message:
54
46
  rdoc_options:
55
47
  - --title
56
- - ActiveTokyoCabinet - a library for using TokyoCabinet under ActiveRecord.
48
+ - ActiveTokyoCabinet - a library for using Tokyo(Cabinet|Tyrant) under ActiveRecord.
57
49
  require_paths:
58
50
  - lib
59
51
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -74,6 +66,6 @@ rubyforge_project: activetokyocabinet
74
66
  rubygems_version: 1.3.5
75
67
  signing_key:
76
68
  specification_version: 3
77
- summary: ActiveTokyoCabinet is a library for using TokyoCabinet under ActiveRecord.
69
+ summary: ActiveTokyoCabinet is a library for using Tokyo(Cabinet|Tyrant) under ActiveRecord.
78
70
  test_files: []
79
71