hyper_record 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CHANGELOG +83 -0
- data/LICENSE +20 -0
- data/README +49 -0
- data/Rakefile +43 -0
- data/VERSION.yml +4 -0
- data/benchmark/save.rb +58 -0
- data/hyper_record.gemspec +76 -0
- data/init.rb +1 -0
- data/lib/active_record/connection_adapters/hyper_table_definition.rb +26 -0
- data/lib/active_record/connection_adapters/hypertable_adapter.rb +680 -0
- data/lib/active_record/connection_adapters/qualified_column.rb +57 -0
- data/lib/associations/hyper_has_and_belongs_to_many_association_extension.rb +107 -0
- data/lib/associations/hyper_has_many_association_extension.rb +87 -0
- data/lib/hyper_record.rb +636 -0
- data/lib/hypertable/gen-rb/client_constants.rb +12 -0
- data/lib/hypertable/gen-rb/client_service.rb +1436 -0
- data/lib/hypertable/gen-rb/client_types.rb +253 -0
- data/lib/hypertable/gen-rb/hql_constants.rb +12 -0
- data/lib/hypertable/gen-rb/hql_service.rb +281 -0
- data/lib/hypertable/gen-rb/hql_types.rb +73 -0
- data/lib/hypertable/thrift_client.rb +94 -0
- data/lib/hypertable/thrift_transport_monkey_patch.rb +29 -0
- data/pkg/hyper_record-0.2.8.gem +0 -0
- data/spec/fixtures/pages.yml +8 -0
- data/spec/fixtures/qualified_pages.yml +1 -0
- data/spec/lib/associations_spec.rb +235 -0
- data/spec/lib/hyper_record_spec.rb +948 -0
- data/spec/lib/hypertable_adapter_spec.rb +121 -0
- data/spec/spec_helper.rb +130 -0
- data/test/test_helper.rb +10 -0
- data/test/thrift_client_test.rb +590 -0
- metadata +99 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../spec_helper.rb')
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
describe HypertableAdapter do
|
6
|
+
before do
|
7
|
+
@h = HypertableAdapter.new(nil, nil, {})
|
8
|
+
end
|
9
|
+
|
10
|
+
describe HypertableAdapter, '.describe_table' do
|
11
|
+
before do
|
12
|
+
@describe_table_text = '<Schema generation="1">\n <AccessGroup name="default">\n <ColumnFamily id="1">\n <Name>message</Name> </ColumnFamily>\n <ColumnFamily id="2">\n <Name>date-time</Name>\n </ColumnFamily>\n </AccessGroup>\n </Schema>\n'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return a string describing a table" do
|
16
|
+
@h.should_receive(:describe_table).with('name').and_return(@describe_table_text)
|
17
|
+
@h.describe_table('name').should == @describe_table_text
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe HypertableAdapter, '.column' do
|
22
|
+
before do
|
23
|
+
@describe_table_text = '<Schema generation="1">\n <AccessGroup name="default">\n <ColumnFamily id="1">\n <Name>message</Name> </ColumnFamily>\n <ColumnFamily id="2">\n <Name>date-time</Name>\n </ColumnFamily>\n </AccessGroup>\n </Schema>\n'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return an array of columns representing the table schema" do
|
27
|
+
@h.stub!(:describe_table).with('name').and_return(@describe_table_text)
|
28
|
+
columns = @h.columns('name')
|
29
|
+
columns.should be_is_a(Array)
|
30
|
+
columns.should have_exactly(3).columns
|
31
|
+
# The first column within a Hypertable is always the row key.
|
32
|
+
columns[0].name.should == "ROW"
|
33
|
+
columns[1].name.should == "message"
|
34
|
+
# notice that the original column name "date-time" is converted
|
35
|
+
# to a Ruby-friendly column name "date_time"
|
36
|
+
columns[2].name.should == "date_time"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should set up the name mappings between ruby and hypertable" do
|
40
|
+
@h.stub!(:describe_table).with('name').and_return(@describe_table_text)
|
41
|
+
columns = @h.columns('name')
|
42
|
+
@h.hypertable_column_name('date_time', 'name').should == 'date-time'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe HypertableAdapter, '.quote_column_name' do
|
47
|
+
it "should surround column name in single quotes" do
|
48
|
+
@h.quote_column_name("date_time").should == "'date_time'"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe HypertableAdapter, '.rubify_column_name' do
|
53
|
+
it "should change dashes to underscores in column names" do
|
54
|
+
@h.rubify_column_name("date-time").should == "date_time"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe HypertableAdapter, '.tables' do
|
59
|
+
before do
|
60
|
+
@tables = ["table1", "table2"]
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return an array of table names" do
|
64
|
+
@h.should_receive(:tables).and_return(@tables)
|
65
|
+
@h.tables.should == @tables
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe HypertableAdapter, '.quote' do
|
70
|
+
it "should return empty string for nil values" do
|
71
|
+
@h.quote(nil).should == ''
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe HypertableAdapter, '.quote' do
|
76
|
+
it "should return a quoted string for all non-nil values" do
|
77
|
+
@h.quote(1).should == "1"
|
78
|
+
@h.quote('happy').should == "happy"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe HypertableAdapter, '.is_qualified_column_name?' do
|
83
|
+
it "should return false for regular columns" do
|
84
|
+
status, family, qualifier = @h.is_qualified_column_name?("col1")
|
85
|
+
status.should be_false
|
86
|
+
family.should == 'col1'
|
87
|
+
qualifier.should be_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should return true for qualified columns" do
|
91
|
+
status, family, qualifier = @h.is_qualified_column_name?("col1:red")
|
92
|
+
status.should be_true
|
93
|
+
family.should == 'col1'
|
94
|
+
qualifier.should == 'red'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe HypertableAdapter, '.create_table_sql' do
|
99
|
+
it "should assemble correct hql for creating a table" do
|
100
|
+
hql = @h.create_table_hql :new_table do |t|
|
101
|
+
t.column :name, :string
|
102
|
+
t.column :value, :string, :max_versions => 1
|
103
|
+
end
|
104
|
+
|
105
|
+
hql.should == "CREATE TABLE 'new_table' ( 'name' , 'value' MAX_VERSIONS=1 )"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe HypertableAdapter, '.create_table_with_block' do
|
110
|
+
it "should assemble correct hql for creating a table" do
|
111
|
+
@h.should_receive(:execute).with("CREATE TABLE 'new_table_with_block' ( 'name' , 'value' MAX_VERSIONS=1 )").and_return(nil)
|
112
|
+
|
113
|
+
@h.create_table :new_table_with_block do |t|
|
114
|
+
t.column :name, :string
|
115
|
+
t.column :value, :string, :max_versions => 1
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "../../../../config/environment"))
|
3
|
+
require 'spec'
|
4
|
+
require 'spec/autorun' # required rspec 1.2.8?
|
5
|
+
require 'spec/rails'
|
6
|
+
|
7
|
+
ActiveRecord::Base.configurations['hypertable'] = {
|
8
|
+
'adapter' => 'hypertable',
|
9
|
+
'host' => 'localhost',
|
10
|
+
'port' => '38080'
|
11
|
+
}
|
12
|
+
ActiveRecord::Base.establish_connection(:hypertable)
|
13
|
+
|
14
|
+
class Dummy < ActiveRecord::HyperBase
|
15
|
+
end
|
16
|
+
|
17
|
+
class Page < ActiveRecord::HyperBase
|
18
|
+
self.establish_connection(:hypertable)
|
19
|
+
|
20
|
+
# mutator_options :persistent => true, :flush_interval => 100
|
21
|
+
|
22
|
+
def self.create_table
|
23
|
+
hql = "CREATE TABLE #{table_name} (
|
24
|
+
'name',
|
25
|
+
'url'
|
26
|
+
)"
|
27
|
+
connection.execute(hql)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class QualifiedPage < ActiveRecord::HyperBase
|
32
|
+
self.establish_connection(:hypertable)
|
33
|
+
qualified_column :misc, :qualifiers => [:name, :url]
|
34
|
+
qualified_column :misc2, :qualifiers => [:foo, :bar]
|
35
|
+
|
36
|
+
def self.create_table
|
37
|
+
hql = "CREATE TABLE #{table_name} (
|
38
|
+
'misc',
|
39
|
+
'misc2'
|
40
|
+
)"
|
41
|
+
connection.execute(hql)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class QualifiedPageWithoutExplicitQualifiers < ActiveRecord::HyperBase
|
46
|
+
QualifiedPageWithoutExplicitQualifiers.set_table_name "qualified_pages"
|
47
|
+
self.establish_connection(:hypertable)
|
48
|
+
qualified_column :misc
|
49
|
+
|
50
|
+
def self.create_table
|
51
|
+
QualifiedPage.create_table
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Spec::Runner.configure do |config|
|
56
|
+
# If you're not using ActiveRecord you should remove these
|
57
|
+
# lines, delete config/database.yml and disable :active_record
|
58
|
+
# in your config/boot.rb
|
59
|
+
config.use_transactional_fixtures = false
|
60
|
+
config.use_instantiated_fixtures = false
|
61
|
+
config.fixture_path = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
|
62
|
+
|
63
|
+
# == Fixtures
|
64
|
+
#
|
65
|
+
# You can declare fixtures for each example_group like this:
|
66
|
+
# describe "...." do
|
67
|
+
# fixtures :table_a, :table_b
|
68
|
+
#
|
69
|
+
# Alternatively, if you prefer to declare them only once, you can
|
70
|
+
# do so right here. Just uncomment the next line and replace the fixture
|
71
|
+
# names with your fixtures.
|
72
|
+
#
|
73
|
+
config.global_fixtures = []
|
74
|
+
|
75
|
+
#
|
76
|
+
# If you declare global fixtures, be aware that they will be declared
|
77
|
+
# for all of your examples, even those that don't use them.
|
78
|
+
#
|
79
|
+
# == Mock Framework
|
80
|
+
#
|
81
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
82
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
83
|
+
#
|
84
|
+
# config.mock_with :mocha
|
85
|
+
# config.mock_with :flexmock
|
86
|
+
# config.mock_with :rr
|
87
|
+
end
|
88
|
+
|
89
|
+
class Fixtures
|
90
|
+
def self.create_fixtures(fixtures_directory, table_names, class_names = {})
|
91
|
+
Page.drop_table
|
92
|
+
Page.create_table
|
93
|
+
QualifiedPage.drop_table
|
94
|
+
QualifiedPage.create_table
|
95
|
+
|
96
|
+
table_names = [table_names].flatten.map { |n| n.to_s }
|
97
|
+
connection = block_given? ? yield : ActiveRecord::Base.connection
|
98
|
+
|
99
|
+
table_names_to_fetch = table_names.reject { |table_name| fixture_is_cached?(connection, table_name) }
|
100
|
+
|
101
|
+
unless table_names_to_fetch.empty?
|
102
|
+
ActiveRecord::Base.silence do
|
103
|
+
connection.disable_referential_integrity do
|
104
|
+
fixtures_map = {}
|
105
|
+
|
106
|
+
fixtures = table_names_to_fetch.map do |table_name|
|
107
|
+
fixtures_map[table_name] = Fixtures.new(connection, File.split(table_name.to_s).last, class_names[table_name.to_sym], File.join(fixtures_directory, table_name.to_s))
|
108
|
+
end
|
109
|
+
|
110
|
+
all_loaded_fixtures.update(fixtures_map)
|
111
|
+
|
112
|
+
connection.transaction(:requires_new => true) do
|
113
|
+
#fixtures.reverse.each {|fixture| fixture.delete_existing_fixtures}
|
114
|
+
fixtures.each {|fixture| fixture.insert_fixtures}
|
115
|
+
|
116
|
+
# Cap primary key sequences to max(pk).
|
117
|
+
if connection.respond_to?(:reset_pk_sequence!)
|
118
|
+
table_names.each do |table_name|
|
119
|
+
connection.reset_pk_sequence!(table_name)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
cache_fixtures(connection, fixtures_map)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
cached_fixtures(connection, table_names)
|
129
|
+
end
|
130
|
+
end
|