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.
@@ -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
- # [singularized, pluralized]
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
- # execute "INSERT INTO #{quote_table_name(table_name)} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert'
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 = TableDefinition.new
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 TableDefinition
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 = Time.now.to_bigrecord_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 = TableDefinition.new
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
- private
314
+ private
314
315
 
315
- def connect
316
- end
316
+ def connect
317
+ end
317
318
 
318
- protected
319
- def log(str, name = nil)
320
- if block_given?
321
- if @logger and @logger.level <= Logger::INFO
322
- result = nil
323
- seconds = Benchmark.realtime { result = yield }
324
- @runtime += seconds
325
- log_info(str, name, seconds)
326
- result
327
- else
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
- log_info(str, name, 0)
332
- nil
330
+ yield
333
331
  end
334
- rescue Exception => e
335
- # Log message and raise exception.
336
- # Set last_verfication to 0, so that connection gets verified
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
- def log_info(str, name, runtime)
345
- return unless @logger
346
-
347
- @logger.debug(
348
- format_log_entry(
349
- "#{name.nil? ? "HBASE" : name} (#{sprintf("%f", runtime)})",
350
- str.gsub(/ +/, " ")
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
- end
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
- log_entry = " \e[#{message_color}m#{message}\e[0m "
366
- log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
367
- log_entry
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
- "%s %s" % [message, dump]
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 TableDefinition
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
@@ -1,5 +1,5 @@
1
1
  module BigRecord
2
- # Big Record automatically timestamps create and update if the table has fields
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>ActiveRecord::Base.default_timezone = :utc</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
- puts "[Bigrecord] ActiveRecord could not be loaded. Bigrecord associations with AR models disabled."
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')
@@ -1,7 +1,7 @@
1
- hbase:
1
+ hbase_rest:
2
2
  adapter: hbase_rest
3
3
  api_address: http://localhost:8080
4
- hbase_brd:
4
+ hbase:
5
5
  adapter: hbase
6
6
  zookeeper_quorum: localhost
7
7
  zookeeper_client_port: 2181