bigrecord 0.0.8 → 0.0.9
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.
- data/README.rdoc +5 -4
- data/VERSION +1 -1
- data/lib/big_record/abstract_base.rb +21 -14
- data/lib/big_record/base.rb +38 -30
- data/lib/big_record/br_associations.rb +100 -773
- data/lib/big_record/br_reflection.rb +1 -3
- data/lib/big_record/connection_adapters/abstract/database_statements.rb +1 -161
- data/lib/big_record/connection_adapters/abstract_adapter.rb +1 -17
- data/lib/big_record/connection_adapters/column.rb +1 -30
- data/lib/big_record/connection_adapters/hbase_adapter.rb +18 -16
- data/lib/big_record/connection_adapters/hbase_rest_adapter.rb +64 -61
- data/lib/big_record/dynamic_schema.rb +14 -0
- data/lib/big_record/embedded_associations/association_proxy.rb +0 -6
- data/lib/big_record/timestamp.rb +28 -2
- data/lib/big_record.rb +1 -4
- data/lib/bigrecord.rb +1 -1
- data/spec/connections/bigrecord.yml +2 -2
- data/spec/debug.log +215 -172
- data/spec/unit/ar_associations_spec.rb +0 -7
- data/spec/unit/{abstract_base_spec.rb → attributes_spec.rb} +20 -3
- data/spec/unit/callback_spec.rb +1 -0
- data/spec/unit/{base_spec.rb → columns_spec.rb} +2 -2
- data/spec/unit/embedded_spec.rb +1 -1
- data/spec/unit/find_spec.rb +10 -0
- data/spec/unit/model_spec.rb +13 -4
- data/spec/unit/scanner_spec.rb +44 -0
- data/tasks/gem.rb +0 -1
- data/tasks/rdoc.rb +1 -1
- metadata +6 -14
@@ -26,11 +26,9 @@ module BigRecord
|
|
26
26
|
# TODO: this sucks... aren't there a better way to do it?
|
27
27
|
if self.class < ActiveRecord::Base
|
28
28
|
class MacroReflectionAbstract < ActiveRecord::Reflection::MacroReflection
|
29
|
-
|
30
29
|
end
|
31
30
|
else
|
32
31
|
class MacroReflectionAbstract < BigRecord::ArReflection::MacroReflection
|
33
|
-
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
@@ -88,7 +86,7 @@ module BigRecord
|
|
88
86
|
|
89
87
|
# Gets an array of possible :through source reflection names
|
90
88
|
#
|
91
|
-
#
|
89
|
+
# [singularized, pluralized]
|
92
90
|
#
|
93
91
|
def source_reflection_names
|
94
92
|
@source_reflection_names ||= (options[:source] ? [options[:source]] : [name.to_s.singularize, name]).collect { |n| n.to_sym }
|
@@ -1,175 +1,15 @@
|
|
1
1
|
module BigRecord
|
2
2
|
module ConnectionAdapters # :nodoc:
|
3
3
|
module DatabaseStatements
|
4
|
-
# # Returns an array of record hashes with the column names as keys and
|
5
|
-
# # column values as values.
|
6
|
-
# def select_all(sql, name = nil)
|
7
|
-
# select(sql, name)
|
8
|
-
# end
|
9
|
-
#
|
10
|
-
# # Returns a record hash with the column names as keys and column values
|
11
|
-
# # as values.
|
12
|
-
# def select_one(sql, name = nil)
|
13
|
-
# result = select_all(sql, name)
|
14
|
-
# result.first if result
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# # Returns a single value from a record
|
18
|
-
# def select_value(sql, name = nil)
|
19
|
-
# if result = select_one(sql, name)
|
20
|
-
# result.values.first
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# # Returns an array of the values of the first column in a select:
|
25
|
-
# # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
26
|
-
# def select_values(sql, name = nil)
|
27
|
-
# result = select_rows(sql, name)
|
28
|
-
# result.map { |v| v[0] }
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# # Returns an array of arrays containing the field values.
|
32
|
-
# # Order is the same as that returned by #columns.
|
33
|
-
# def select_rows(sql, name = nil)
|
34
|
-
# raise NotImplementedError, "select_rows is an abstract method"
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# # Executes the SQL statement in the context of this connection.
|
38
|
-
# def execute(sql, name = nil)
|
39
|
-
# raise NotImplementedError, "execute is an abstract method"
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# # Returns the last auto-generated ID from the affected table.
|
43
|
-
# def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
44
|
-
# insert_sql(sql, name, pk, id_value, sequence_name)
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
# # Executes the update statement and returns the number of rows affected.
|
48
|
-
# def update(sql, name = nil)
|
49
|
-
# update_sql(sql, name)
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# # Executes the delete statement and returns the number of rows affected.
|
53
|
-
# def delete(sql, name = nil)
|
54
|
-
# delete_sql(sql, name)
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# # Wrap a block in a transaction. Returns result of block.
|
58
|
-
# def transaction(start_db_transaction = true)
|
59
|
-
# transaction_open = false
|
60
|
-
# begin
|
61
|
-
# if block_given?
|
62
|
-
# if start_db_transaction
|
63
|
-
# begin_db_transaction
|
64
|
-
# transaction_open = true
|
65
|
-
# end
|
66
|
-
# yield
|
67
|
-
# end
|
68
|
-
# rescue Exception => database_transaction_rollback
|
69
|
-
# if transaction_open
|
70
|
-
# transaction_open = false
|
71
|
-
# rollback_db_transaction
|
72
|
-
# end
|
73
|
-
# raise unless database_transaction_rollback.is_a? ActiveRecord::Rollback
|
74
|
-
# end
|
75
|
-
# ensure
|
76
|
-
# if transaction_open
|
77
|
-
# begin
|
78
|
-
# commit_db_transaction
|
79
|
-
# rescue Exception => database_transaction_rollback
|
80
|
-
# rollback_db_transaction
|
81
|
-
# raise
|
82
|
-
# end
|
83
|
-
# end
|
84
|
-
# end
|
85
|
-
#
|
86
|
-
# # Begins the transaction (and turns off auto-committing).
|
87
|
-
# def begin_db_transaction() end
|
88
|
-
#
|
89
|
-
# # Commits the transaction (and turns on auto-committing).
|
90
|
-
# def commit_db_transaction() end
|
91
|
-
#
|
92
|
-
# # Rolls back the transaction (and turns on auto-committing). Must be
|
93
|
-
# # done if the transaction block raises an exception or returns false.
|
94
|
-
# def rollback_db_transaction() end
|
95
|
-
#
|
96
|
-
# # Alias for #add_limit_offset!.
|
97
|
-
# def add_limit!(sql, options)
|
98
|
-
# add_limit_offset!(sql, options) if options
|
99
|
-
# end
|
100
|
-
#
|
101
|
-
# # Appends +LIMIT+ and +OFFSET+ options to an SQL statement.
|
102
|
-
# # This method *modifies* the +sql+ parameter.
|
103
|
-
# # ===== Examples
|
104
|
-
# # add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
|
105
|
-
# # generates
|
106
|
-
# # SELECT * FROM suppliers LIMIT 10 OFFSET 50
|
107
|
-
# def add_limit_offset!(sql, options)
|
108
|
-
# if limit = options[:limit]
|
109
|
-
# sql << " LIMIT #{limit}"
|
110
|
-
# if offset = options[:offset]
|
111
|
-
# sql << " OFFSET #{offset}"
|
112
|
-
# end
|
113
|
-
# end
|
114
|
-
# end
|
115
|
-
#
|
116
|
-
# # Appends a locking clause to an SQL statement.
|
117
|
-
# # This method *modifies* the +sql+ parameter.
|
118
|
-
# # # SELECT * FROM suppliers FOR UPDATE
|
119
|
-
# # add_lock! 'SELECT * FROM suppliers', :lock => true
|
120
|
-
# # add_lock! 'SELECT * FROM suppliers', :lock => ' FOR UPDATE'
|
121
|
-
# def add_lock!(sql, options)
|
122
|
-
# case lock = options[:lock]
|
123
|
-
# when true; sql << ' FOR UPDATE'
|
124
|
-
# when String; sql << " #{lock}"
|
125
|
-
# end
|
126
|
-
# end
|
127
|
-
#
|
128
|
-
# def default_sequence_name(table, column)
|
129
|
-
# nil
|
130
|
-
# end
|
131
|
-
#
|
132
|
-
# # Set the sequence to the max value of the table's column.
|
133
|
-
# def reset_sequence!(table, column, sequence = nil)
|
134
|
-
# # Do nothing by default. Implement for PostgreSQL, Oracle, ...
|
135
|
-
# end
|
136
|
-
|
137
4
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
138
5
|
# something beyond a simple insert (eg. Oracle).
|
139
6
|
def insert_fixture(fixture, table_name)
|
140
|
-
#
|
7
|
+
# execute "INSERT INTO #{quote_table_name(table_name)} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert'
|
141
8
|
attributes = fixture.to_hash.dup
|
142
9
|
id = attributes.delete("id")
|
143
10
|
raise ArgumentError, "the id is missing" unless id
|
144
11
|
update(table_name, id, attributes, Time.now.to_bigrecord_timestamp)
|
145
12
|
end
|
146
|
-
|
147
|
-
# def empty_insert_statement(table_name)
|
148
|
-
# "INSERT INTO #{quote_table_name(table_name)} VALUES(DEFAULT)"
|
149
|
-
# end
|
150
|
-
#
|
151
|
-
# protected
|
152
|
-
# # Returns an array of record hashes with the column names as keys and
|
153
|
-
# # column values as values.
|
154
|
-
# def select(sql, name = nil)
|
155
|
-
# raise NotImplementedError, "select is an abstract method"
|
156
|
-
# end
|
157
|
-
#
|
158
|
-
# # Returns the last auto-generated ID from the affected table.
|
159
|
-
# def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
160
|
-
# execute(sql, name)
|
161
|
-
# id_value
|
162
|
-
# end
|
163
|
-
#
|
164
|
-
# # Executes the update statement and returns the number of rows affected.
|
165
|
-
# def update_sql(sql, name = nil)
|
166
|
-
# execute(sql, name)
|
167
|
-
# end
|
168
|
-
#
|
169
|
-
# # Executes the delete statement and returns the number of rows affected.
|
170
|
-
# def delete_sql(sql, name = nil)
|
171
|
-
# update_sql(sql, name)
|
172
|
-
# end
|
173
13
|
end
|
174
14
|
end
|
175
15
|
end
|
@@ -7,7 +7,7 @@ module BigRecord
|
|
7
7
|
module ConnectionAdapters # :nodoc:
|
8
8
|
# All the concrete database adapters follow the interface laid down in this class.
|
9
9
|
# You can use this interface directly by borrowing the database connection from the Base with
|
10
|
-
# Base.connection
|
10
|
+
# BigRecord::Base.connection
|
11
11
|
#
|
12
12
|
# Most of the methods in the adapter are useful during migrations. Most
|
13
13
|
# notably, SchemaStatements#create_table, SchemaStatements#drop_table,
|
@@ -172,19 +172,3 @@ module BigRecord
|
|
172
172
|
end # class AbstractAdapter
|
173
173
|
end # module ConnectionAdapters
|
174
174
|
end # module BigRecord
|
175
|
-
|
176
|
-
|
177
|
-
# Open the time class to add logic for the hbase timestamp
|
178
|
-
class Time
|
179
|
-
# Return this time is the hbase timestamp format, i.e. a 'long'. The 4 high bytes contain
|
180
|
-
# the number of seconds since epoch and the 4 low bytes contain the microseconds. That
|
181
|
-
# format is an arbitrary one and could have been something else.
|
182
|
-
def to_bigrecord_timestamp
|
183
|
-
(self.to_i << 32) + self.usec
|
184
|
-
end
|
185
|
-
|
186
|
-
def self.from_bigrecord_timestamp(timestamp)
|
187
|
-
Time.at(timestamp >> 32, timestamp & 0xFFFFFFFF)
|
188
|
-
end
|
189
|
-
|
190
|
-
end
|
@@ -103,6 +103,7 @@ module BigRecord
|
|
103
103
|
end
|
104
104
|
|
105
105
|
# Returns the Ruby class that corresponds to the abstract data type.
|
106
|
+
# View the source for the actual mappings.
|
106
107
|
def klass
|
107
108
|
@klass ||=
|
108
109
|
case type
|
@@ -339,36 +340,6 @@ module BigRecord
|
|
339
340
|
parse_collection(value).collect{|v| string_to_dummy_time(v.to_s)}
|
340
341
|
end
|
341
342
|
|
342
|
-
# def hash_to_time_collection(hash)
|
343
|
-
# return []
|
344
|
-
# return hash unless hash.is_a?(Hash)
|
345
|
-
# hash_to_collection(hash).collect do |attributes|
|
346
|
-
# cleaned_attributes = {}
|
347
|
-
# debugger
|
348
|
-
# attributes.each do |k, v|
|
349
|
-
# k =~ /reflect_value(.*)/
|
350
|
-
# cleaned_attributes[$1] = v
|
351
|
-
# end
|
352
|
-
# string_to_time(cleaned_attributes)
|
353
|
-
# end
|
354
|
-
# end
|
355
|
-
#
|
356
|
-
# def hash_to_dummy_time_collection(hash)
|
357
|
-
# return []
|
358
|
-
# return hash unless hash.is_a?(Array)
|
359
|
-
# hash.split(COLLECTION_SEPARATOR).collect{|v|string_to_dummy_time(v)}
|
360
|
-
# end
|
361
|
-
#
|
362
|
-
# def hash_to_date_collection(hash)
|
363
|
-
# return []
|
364
|
-
# return hash unless hash.is_a?(Array)
|
365
|
-
# hash_to_collection(hash).collect do |attributes|
|
366
|
-
# debugger
|
367
|
-
# callstack = extract_callstack_for_multiparameter_attributes(attributes.to_a)
|
368
|
-
#
|
369
|
-
# end
|
370
|
-
# end
|
371
|
-
|
372
343
|
def hash_to_boolean_collection(value)
|
373
344
|
parse_collection(value).collect{|v| value_to_boolean(v)}
|
374
345
|
end
|
@@ -2,24 +2,26 @@ require 'rubygems'
|
|
2
2
|
require 'set'
|
3
3
|
require 'drb'
|
4
4
|
|
5
|
-
unless defined?(BigRecordDriver)
|
6
|
-
begin
|
7
|
-
# Bigrecord's source is included with Bigrecord-Driver, that's we check for this first
|
8
|
-
require File.join(File.dirname(__FILE__), "..", "..", "..", "..", "bigrecord-driver", "lib", "big_record_driver")
|
9
|
-
rescue LoadError
|
10
|
-
begin
|
11
|
-
gem 'bigrecord-driver'
|
12
|
-
require 'bigrecord_driver'
|
13
|
-
rescue Gem::LoadError
|
14
|
-
puts "bigrecord-driver not available. Install it with: sudo gem install bigrecord-driver -s http://gemcutter.org"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
5
|
module BigRecord
|
20
6
|
class Base
|
21
7
|
# Establishes a connection to the database that's used by all Active Record objects.
|
22
8
|
def self.hbase_connection(config) # :nodoc:
|
9
|
+
unless defined?(BigRecordDriver)
|
10
|
+
begin
|
11
|
+
# Bigrecord's source is included with Bigrecord-Driver, that's where we check for it first.
|
12
|
+
require File.join(File.dirname(__FILE__), "..", "..", "..", "..", "bigrecord-driver", "lib", "big_record_driver")
|
13
|
+
rescue LoadError
|
14
|
+
# Then we'll require it from the load path (or rubygems)
|
15
|
+
begin
|
16
|
+
require 'bigrecord_driver'
|
17
|
+
rescue LoadError => e
|
18
|
+
# If it couldn't be found, we'll just prompt the user to install the gem.
|
19
|
+
puts "[BigRecord] bigrecord-driver is needed for HbaseAdapter. Install it with: gem install bigrecord-driver"
|
20
|
+
raise e
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
23
25
|
config = config.symbolize_keys
|
24
26
|
|
25
27
|
zookeeper_host = config[:zookeeper_host]
|
@@ -233,7 +235,7 @@ module BigRecord
|
|
233
235
|
end
|
234
236
|
|
235
237
|
def create_table(table_name, options = {})
|
236
|
-
table_definition =
|
238
|
+
table_definition = HbaseAdapterTable.new
|
237
239
|
|
238
240
|
yield table_definition if block_given?
|
239
241
|
|
@@ -398,7 +400,7 @@ module BigRecord
|
|
398
400
|
end
|
399
401
|
end
|
400
402
|
|
401
|
-
class
|
403
|
+
class HbaseAdapterTable
|
402
404
|
|
403
405
|
def initialize
|
404
406
|
@column_families = []
|
@@ -1,22 +1,27 @@
|
|
1
1
|
require 'set'
|
2
|
-
require 'hbase'
|
3
2
|
|
4
3
|
module BigRecord
|
5
4
|
class Base
|
6
5
|
# Establishes a connection to the database that's used by all Active Record objects.
|
7
6
|
def self.hbase_rest_connection(config) # :nodoc:
|
7
|
+
begin
|
8
|
+
require 'hbase'
|
9
|
+
rescue LoadError => e
|
10
|
+
puts "[BigRecord] hbase-ruby is needed for HbaseRestAdapter. Install it with: gem install hbase-ruby"
|
11
|
+
raise e
|
12
|
+
end
|
13
|
+
|
8
14
|
config = config.symbolize_keys
|
9
15
|
|
10
16
|
api_address = config[:api_address]
|
11
|
-
|
12
17
|
hbase = HBase::Client.new(api_address)
|
13
|
-
|
14
18
|
ConnectionAdapters::HbaseRestAdapter.new(hbase, logger, [], config)
|
15
19
|
end
|
16
20
|
end
|
17
21
|
|
18
22
|
module ConnectionAdapters
|
19
23
|
class HbaseRestAdapter < AbstractAdapter
|
24
|
+
|
20
25
|
@@emulate_booleans = true
|
21
26
|
cattr_accessor :emulate_booleans
|
22
27
|
|
@@ -83,7 +88,7 @@ module BigRecord
|
|
83
88
|
result = nil
|
84
89
|
|
85
90
|
columns = columns_to_hbase_format(values)
|
86
|
-
timestamp
|
91
|
+
timestamp ||= Time.now.to_bigrecord_timestamp
|
87
92
|
|
88
93
|
log "UPDATE #{table_name} SET #{values.inspect if values} WHERE ROW=#{row};" do
|
89
94
|
@connection.create_row(table_name, row, timestamp, columns)
|
@@ -171,16 +176,12 @@ module BigRecord
|
|
171
176
|
|
172
177
|
result = rows.collect do |row|
|
173
178
|
cols = {}
|
179
|
+
cols['id'] = row.name
|
174
180
|
row.columns.each do |col|
|
175
181
|
key = col.name
|
176
182
|
value = col.value
|
177
183
|
begin
|
178
|
-
cols[key] =
|
179
|
-
if key == 'id'
|
180
|
-
value
|
181
|
-
else
|
182
|
-
deserialize(value)
|
183
|
-
end
|
184
|
+
cols[key] = deserialize(value)
|
184
185
|
rescue Exception => e
|
185
186
|
puts "Could not load column value #{key} for row=#{row.name}"
|
186
187
|
end
|
@@ -228,7 +229,7 @@ module BigRecord
|
|
228
229
|
end
|
229
230
|
|
230
231
|
def create_table(table_name, options = {})
|
231
|
-
table_definition =
|
232
|
+
table_definition = HbaseRestAdapterTable.new
|
232
233
|
|
233
234
|
yield table_definition if block_given?
|
234
235
|
|
@@ -310,68 +311,70 @@ module BigRecord
|
|
310
311
|
end
|
311
312
|
end
|
312
313
|
|
313
|
-
|
314
|
+
private
|
314
315
|
|
315
|
-
|
316
|
-
|
316
|
+
def connect
|
317
|
+
end
|
317
318
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
yield
|
329
|
-
end
|
319
|
+
protected
|
320
|
+
|
321
|
+
def log(str, name = nil)
|
322
|
+
if block_given?
|
323
|
+
if @logger and @logger.level <= Logger::INFO
|
324
|
+
result = nil
|
325
|
+
seconds = Benchmark.realtime { result = yield }
|
326
|
+
@runtime += seconds
|
327
|
+
log_info(str, name, seconds)
|
328
|
+
result
|
330
329
|
else
|
331
|
-
|
332
|
-
nil
|
330
|
+
yield
|
333
331
|
end
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
# upon reentering the request loop
|
338
|
-
@last_verification = 0
|
339
|
-
message = "#{e.class.name}: #{e.message}: #{str}"
|
340
|
-
log_info(message, name, 0)
|
341
|
-
raise e
|
332
|
+
else
|
333
|
+
log_info(str, name, 0)
|
334
|
+
nil
|
342
335
|
end
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
336
|
+
rescue Exception => e
|
337
|
+
# Log message and raise exception.
|
338
|
+
# Set last_verfication to 0, so that connection gets verified
|
339
|
+
# upon reentering the request loop
|
340
|
+
@last_verification = 0
|
341
|
+
message = "#{e.class.name}: #{e.message}: #{str}"
|
342
|
+
log_info(message, name, 0)
|
343
|
+
raise e
|
344
|
+
end
|
345
|
+
|
346
|
+
def log_info(str, name, runtime)
|
347
|
+
return unless @logger
|
348
|
+
|
349
|
+
@logger.debug(
|
350
|
+
format_log_entry(
|
351
|
+
"#{name.nil? ? "HBASE" : name} (#{sprintf("%f", runtime)})",
|
352
|
+
str.gsub(/ +/, " ")
|
352
353
|
)
|
353
|
-
|
354
|
-
|
355
|
-
def format_log_entry(message, dump = nil)
|
356
|
-
if BigRecord::Base.colorize_logging
|
357
|
-
if @@row_even
|
358
|
-
@@row_even = false
|
359
|
-
message_color, dump_color = "4;36;1", "0;1"
|
360
|
-
else
|
361
|
-
@@row_even = true
|
362
|
-
message_color, dump_color = "4;35;1", "0"
|
363
|
-
end
|
354
|
+
)
|
355
|
+
end
|
364
356
|
|
365
|
-
|
366
|
-
|
367
|
-
|
357
|
+
def format_log_entry(message, dump = nil)
|
358
|
+
if BigRecord::Base.colorize_logging
|
359
|
+
if @@row_even
|
360
|
+
@@row_even = false
|
361
|
+
message_color, dump_color = "4;36;1", "0;1"
|
368
362
|
else
|
369
|
-
|
363
|
+
@@row_even = true
|
364
|
+
message_color, dump_color = "4;35;1", "0"
|
370
365
|
end
|
366
|
+
|
367
|
+
log_entry = " \e[#{message_color}m#{message}\e[0m "
|
368
|
+
log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
|
369
|
+
log_entry
|
370
|
+
else
|
371
|
+
"%s %s" % [message, dump]
|
371
372
|
end
|
373
|
+
end
|
374
|
+
|
372
375
|
end
|
373
376
|
|
374
|
-
class
|
377
|
+
class HbaseRestAdapterTable
|
375
378
|
|
376
379
|
##
|
377
380
|
# Given an column descriptor's options hash from Bigrecord, translate it into
|
@@ -1,4 +1,18 @@
|
|
1
1
|
module BigRecord
|
2
|
+
|
3
|
+
# = Dynamic Schema
|
4
|
+
#
|
5
|
+
# The dynamic schema functionality of Bigrecord refers to the ability to
|
6
|
+
# modify the attributes of a model within the class itself, rather than being
|
7
|
+
# bounded by the database. This is an inherit property of using the BigTable
|
8
|
+
# database model, and Bigrecord leverages its use.
|
9
|
+
#
|
10
|
+
# New attributes defined will simply return nil for records that existed
|
11
|
+
# before their addition into the model, while attributes that are removed
|
12
|
+
# from the model will just be ignored when accessing existing records.
|
13
|
+
#
|
14
|
+
# Refer to {BigRecord::ConnectionAdapters::Column} for more information.
|
15
|
+
#
|
2
16
|
module DynamicSchema
|
3
17
|
|
4
18
|
def self.included(base) #:nodoc:
|
@@ -3,12 +3,6 @@ module BigRecord
|
|
3
3
|
class AssociationProxy #:nodoc:
|
4
4
|
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_)/ }
|
5
5
|
|
6
|
-
# def initialize(owner, reflection)
|
7
|
-
# @owner, @reflection = owner, reflection
|
8
|
-
# Array(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
|
9
|
-
# reset
|
10
|
-
# end
|
11
|
-
|
12
6
|
def find(id)
|
13
7
|
@target.select{|s| s.id == id}.first
|
14
8
|
end
|
data/lib/big_record/timestamp.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module BigRecord
|
2
|
-
#
|
2
|
+
# BigRecord automatically timestamps create and update if the table has fields
|
3
3
|
# created_at/created_on or updated_at/updated_on.
|
4
4
|
#
|
5
5
|
# Timestamping can be turned off by setting
|
@@ -15,7 +15,7 @@ module BigRecord
|
|
15
15
|
# end
|
16
16
|
#
|
17
17
|
# Timestamps are in the local timezone by default but can use UTC by setting
|
18
|
-
# <tt>
|
18
|
+
# <tt>BigRecord::Base.default_timezone = :utc</tt>
|
19
19
|
module Timestamp
|
20
20
|
def self.included(base) #:nodoc:
|
21
21
|
super
|
@@ -49,3 +49,29 @@ module BigRecord
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
# Open the Time class to add methods which convert the time into the Bigrecord
|
54
|
+
# timestamp format.
|
55
|
+
class Time
|
56
|
+
|
57
|
+
# Return the time in the Bigrecord timestamp format, i.e. a 'long' where the
|
58
|
+
# 4 high bytes contain the number of seconds since epoch and the 4 low bytes
|
59
|
+
# contain the microseconds.
|
60
|
+
#
|
61
|
+
# @example
|
62
|
+
# > Time.now.to_bigrecord_timestamp
|
63
|
+
# => 5410405886576175030
|
64
|
+
def to_bigrecord_timestamp
|
65
|
+
(self.to_i << 32) + self.usec
|
66
|
+
end
|
67
|
+
|
68
|
+
# Converts a timestamp in Bigrecord format into a regular Time object.
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# > Time.from_bigrecord_timestamp(5410405886576175030)
|
72
|
+
# => Tue Dec 01 17:58:05 -0500 2009
|
73
|
+
def self.from_bigrecord_timestamp(timestamp)
|
74
|
+
Time.at(timestamp >> 32, timestamp & 0xFFFFFFFF)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
data/lib/big_record.rb
CHANGED
@@ -32,7 +32,7 @@ end
|
|
32
32
|
begin
|
33
33
|
require 'active_record'
|
34
34
|
rescue LoadError
|
35
|
-
|
35
|
+
raise LoadError, "Bigrecord depends on ActiveRecord. Install it with: gem install activerecord"
|
36
36
|
end
|
37
37
|
|
38
38
|
require dir + '/routing_ext'
|
@@ -40,7 +40,6 @@ require dir + '/abstract_base'
|
|
40
40
|
require dir + '/base'
|
41
41
|
require dir + '/embedded'
|
42
42
|
require dir + '/validations'
|
43
|
-
#require dir + '/callbacks'
|
44
43
|
require dir + '/ar_reflection'
|
45
44
|
require dir + '/br_reflection'
|
46
45
|
require dir + '/ar_associations'
|
@@ -60,7 +59,6 @@ require dir + '/action_view_extensions'
|
|
60
59
|
|
61
60
|
BigRecord::Base.class_eval do
|
62
61
|
include BigRecord::Validations
|
63
|
-
# include BigRecord::Callbacks
|
64
62
|
include ActiveRecord::Callbacks
|
65
63
|
include BigRecord::Timestamp
|
66
64
|
include BigRecord::ArAssociations
|
@@ -75,7 +73,6 @@ end
|
|
75
73
|
|
76
74
|
BigRecord::Embedded.class_eval do
|
77
75
|
include BigRecord::Validations
|
78
|
-
# include BigRecord::Callbacks
|
79
76
|
include ActiveRecord::Callbacks
|
80
77
|
include BigRecord::Timestamp
|
81
78
|
include BigRecord::ArAssociations
|
data/lib/bigrecord.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'big_record'
|
1
|
+
require File.join(File.dirname(__FILE__), 'big_record')
|