Class: ActiveRecord::HyperBase
- Inherits:
-
Base
- Object
- Base
- ActiveRecord::HyperBase
show all
- Defined in:
- lib/hyper_record.rb
Constant Summary
collapse
- BILLION =
1_000_000_000.0
- ROW_KEY_OFFSET =
0
- COLUMN_FAMILY_OFFSET =
1
- COLUMN_QUALIFIER_OFFSET =
2
- VALUE_OFFSET =
3
- TIMESTAMP_OFFSET =
4
Class Attribute Summary collapse
Class Method Summary
collapse
-
.abstract_class? ⇒ Boolean
-
.close_mutator(mutator, flush = true) ⇒ Object
-
.close_scanner(scanner) ⇒ Object
-
.column_families_without_row_key ⇒ Object
-
.columns ⇒ Object
Returns array of column objects for table associated with this class.
-
.convert_cells_to_hashes(cells) ⇒ Object
-
.convert_cells_to_instantiated_rows(cells) ⇒ Object
-
.delete(*ids) ⇒ Object
-
.drop_table ⇒ Object
-
.each_cell(scanner, &block) ⇒ Object
-
.each_cell_as_arrays(scanner, &block) ⇒ Object
-
.each_row(scanner, &block) ⇒ Object
-
.each_row_as_arrays(scanner, &block) ⇒ Object
-
.exists?(id_or_conditions) ⇒ Boolean
-
.find(*args) ⇒ Object
-
.find_by_hql(hql) ⇒ Object
(also: find_by_sql)
-
.find_by_options(options) ⇒ Object
-
.find_each_row(*args) ⇒ Object
Returns each row matching the finder options as a HyperRecord object.
-
.find_each_row_as_arrays(*args) ⇒ Object
Returns each row matching the finder options as an array of cells in native array format.
-
.find_from_ids(ids, options) ⇒ Object
-
.find_initial(options) ⇒ Object
-
.find_one(id, options) ⇒ Object
-
.find_some(ids, options) ⇒ Object
-
.find_to_scan_spec(*args) ⇒ Object
-
.find_with_scanner(*args, &block) ⇒ Object
-
.flush_mutator(mutator) ⇒ Object
-
.open_mutator ⇒ Object
Return an open mutator on this table.
-
.open_scanner(scan_spec) ⇒ Object
-
.primary_key ⇒ Object
Returns the primary key field for a table.
-
.qualified?(column_name) ⇒ Boolean
-
.qualified_column(*attrs) ⇒ Object
-
.qualified_column_names_without_row_key ⇒ Object
-
.quoted_column_names(attributes = attributes_with_quotes) ⇒ Object
-
.set_default_options(options) ⇒ Object
-
.table_exists?(name = table_name) ⇒ Boolean
-
.with_scanner(scan_spec, &block) ⇒ Object
-
.with_thrift_client ⇒ Object
Instance Method Summary
collapse
-
#attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true) ⇒ Object
Returns a copy of the attributes hash where all the values have been safely quoted for insertion.
-
#create(mutator = nil) ⇒ Object
-
#create_or_update_with_mutator(mutator) ⇒ Object
-
#decrement(attribute, by = 1) ⇒ Object
-
#decrement!(attribute, by = 1) ⇒ Object
-
#delete_cells(cells, table = self.class.table_name) ⇒ Object
Delete an array of cells from Hypertable cells is an array of cell keys [[“row”, “column”], …].
-
#delete_rows(row_keys, table = self.class.table_name) ⇒ Object
Delete an array of rows from Hypertable rows is an array of row keys [“row1”, “row2”, …].
-
#destroy ⇒ Object
-
#increment(attribute, by = 1) ⇒ Object
-
#increment!(attribute, by = 1) ⇒ Object
-
#initialize(attrs = {}) ⇒ HyperBase
constructor
A new instance of HyperBase.
-
#quoted_attributes_to_cells(quoted_attrs, table = self.class.table_name) ⇒ Object
Translates the output of attributes_with_quotes into an array of cells suitable for writing into Hypertable (through the write_cells method).
-
#save_with_mutator(mutator) ⇒ Object
-
#save_with_mutator!(mutator) ⇒ Object
-
#update(mutator = nil) ⇒ Object
-
#write_cells(cells, table = self.class.table_name, mutator = nil) ⇒ Object
Write an array of cells to Hypertable.
-
#write_quoted_attributes(quoted_attrs, table = self.class.table_name, mutator = nil) ⇒ Object
Methods inherited from Base
hypertable_connection, inherited, require_hypertable_thrift_client
Constructor Details
#initialize(attrs = {}) ⇒ HyperBase
Returns a new instance of HyperBase.
31
32
33
34
|
# File 'lib/hyper_record.rb', line 31
def initialize(attrs={})
super(attrs)
self.ROW = attrs[:ROW] if attrs[:ROW] && attrs[:ROW]
end
|
Class Attribute Details
.qualified_columns ⇒ Object
qualified_column :misc, :qualifiers => [:name, :url]
472
473
474
|
# File 'lib/hyper_record.rb', line 472
def qualified_columns
@qualified_columns
end
|
Class Method Details
.abstract_class? ⇒ Boolean
184
185
186
|
# File 'lib/hyper_record.rb', line 184
def abstract_class?
self == ActiveRecord::HyperBase
end
|
.close_mutator(mutator, flush = true) ⇒ Object
492
493
494
|
# File 'lib/hyper_record.rb', line 492
def close_mutator(mutator, flush=true)
self.connection.close_mutator(mutator, flush)
end
|
.close_scanner(scanner) ⇒ Object
505
506
507
|
# File 'lib/hyper_record.rb', line 505
def close_scanner(scanner)
self.connection.close_scanner(scanner)
end
|
.column_families_without_row_key ⇒ Object
456
457
458
|
# File 'lib/hyper_record.rb', line 456
def column_families_without_row_key
columns[1,columns.length]
end
|
.columns ⇒ Object
Returns array of column objects for table associated with this class.
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
|
# File 'lib/hyper_record.rb', line 429
def columns
unless @columns
@columns = connection.columns(table_name, "#{name} Columns")
@qualified_columns ||= []
@qualified_columns.each{|qc|
@columns = @columns.reject{|c| c.name == qc[:column_name].to_s}
connection.remove_column_from_name_map(table_name, qc[:column_name].to_s)
@columns << connection.add_qualified_column(table_name, qc[:column_name].to_s, qc[:qualifiers])
}
@columns.each {|column| column.primary = column.name == primary_key}
end
@columns
end
|
.convert_cells_to_hashes(cells) ⇒ Object
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
|
# File 'lib/hyper_record.rb', line 320
def convert_cells_to_hashes(cells)
rows = []
current_row = {}
cells.each_with_index do |cell, i|
current_row['ROW'] = cell[ROW_KEY_OFFSET]
family = connection.rubify_column_name(cell[COLUMN_FAMILY_OFFSET])
if !cell[COLUMN_QUALIFIER_OFFSET].blank?
current_row[family] ||= {}
current_row[family][cell[COLUMN_QUALIFIER_OFFSET]] = cell[VALUE_OFFSET]
else
current_row[family] = cell[VALUE_OFFSET]
end
next_index = i + 1
if (cells[next_index] and cells[next_index][ROW_KEY_OFFSET] != current_row['ROW']) or next_index >= cells.length
for col in column_families_without_row_key
if !current_row.has_key?(col.name)
if col.is_a?(ActiveRecord::ConnectionAdapters::QualifiedColumn)
current_row[col.name] = {}
else
current_row[col.name] = nil
end
end
end
rows << current_row
current_row = {}
end
end
rows
end
|
.convert_cells_to_instantiated_rows(cells) ⇒ Object
367
368
369
|
# File 'lib/hyper_record.rb', line 367
def convert_cells_to_instantiated_rows(cells)
convert_cells_to_hashes(cells).map{|row| instantiate(row)}
end
|
.delete(*ids) ⇒ Object
199
200
201
|
# File 'lib/hyper_record.rb', line 199
def delete(*ids)
self.connection.delete_rows(table_name, ids.flatten)
end
|
.drop_table ⇒ Object
417
418
419
|
# File 'lib/hyper_record.rb', line 417
def drop_table
connection.drop_table(table_name) if table_exists?
end
|
.each_cell(scanner, &block) ⇒ Object
514
515
516
|
# File 'lib/hyper_record.rb', line 514
def each_cell(scanner, &block)
self.connection.each_cell(scanner, &block)
end
|
.each_cell_as_arrays(scanner, &block) ⇒ Object
518
519
520
|
# File 'lib/hyper_record.rb', line 518
def each_cell_as_arrays(scanner, &block)
self.connection.each_cell_as_arrays(scanner, &block)
end
|
.each_row(scanner, &block) ⇒ Object
522
523
524
|
# File 'lib/hyper_record.rb', line 522
def each_row(scanner, &block)
self.connection.each_row(scanner, &block)
end
|
.each_row_as_arrays(scanner, &block) ⇒ Object
526
527
528
|
# File 'lib/hyper_record.rb', line 526
def each_row_as_arrays(scanner, &block)
self.connection.each_row_as_arrays(scanner, &block)
end
|
.exists?(id_or_conditions) ⇒ Boolean
188
189
190
191
192
193
194
195
196
197
|
# File 'lib/hyper_record.rb', line 188
def exists?(id_or_conditions)
case id_or_conditions
when Fixnum, String
!find(:first, :row_keys => [id_or_conditions]).nil?
when Hash
!find(:first, :conditions => id_or_conditions).nil?
else
raise "only Fixnum, String and Hash arguments supported"
end
end
|
.find(*args) ⇒ Object
203
204
205
206
207
208
209
210
211
|
# File 'lib/hyper_record.rb', line 203
def find(*args)
options = args.
case args.first
when :first then find_initial(options)
when :all then find_by_options(options)
else find_from_ids(args, options)
end
end
|
.find_by_hql(hql) ⇒ Object
Also known as:
find_by_sql
371
372
373
374
375
376
377
|
# File 'lib/hyper_record.rb', line 371
def find_by_hql(hql)
hql_result = connection.execute(hql)
cells_in_native_array_format = hql_result.cells.map do |c|
connection.cell_native_array(c.row_key, c.column_family, c.column_qualifier, c.value)
end
convert_cells_to_instantiated_rows(cells_in_native_array_format)
end
|
.find_by_options(options) ⇒ Object
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
|
# File 'lib/hyper_record.rb', line 289
def find_by_options(options)
set_default_options(options)
if options[:scan_spec]
return connection.convert_options_to_scan_spec(options)
end
cells = connection.execute_with_options(options)
if HyperBase.log_calls
msg = [ "Select" ]
for key in options.keys
case key
when :columns
msg << " columns\t#{options[:columns].map{|c| c.name}.join(',')}"
else
msg << " #{key}\t#{options[key]}"
end
end
msg << "Returned #{cell_count} cells"
RAILS_DEFAULT_LOGGER.info(msg)
end
convert_cells_to_instantiated_rows(cells)
end
|
.find_each_row(*args) ⇒ Object
Returns each row matching the finder options as a HyperRecord object. Each object is yielded to the caller so that large queries can be processed one object at a time without pulling the entire result set into memory.
Page.find_each_row(:all) do |page|
...
end
233
234
235
236
237
|
# File 'lib/hyper_record.rb', line 233
def find_each_row(*args)
find_each_row_as_arrays(*args) do |row|
yield convert_cells_to_instantiated_rows(row).first
end
end
|
.find_each_row_as_arrays(*args) ⇒ Object
Returns each row matching the finder options as an array of cells in native array format. Each row is yielded to the caller so that large queries can be processed one row at a time without pulling the entire result set into memory.
Page.find_each_row(:all) do |page_as_array_of_cells|
...
end
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
|
# File 'lib/hyper_record.rb', line 247
def find_each_row_as_arrays(*args)
scan_spec = find_to_scan_spec(*args)
with_scanner(scan_spec) do |scanner|
row = []
current_row_key = nil
each_cell_as_arrays(scanner) do |cell|
current_row_key ||= cell[ROW_KEY_OFFSET]
if cell[ROW_KEY_OFFSET] == current_row_key
row << cell
else
yield row
row = [cell]
current_row_key = cell[ROW_KEY_OFFSET]
end
end
yield row unless row.empty?
end
end
|
.find_from_ids(ids, options) ⇒ Object
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
|
# File 'lib/hyper_record.rb', line 380
def find_from_ids(ids, options)
expects_array = ids.first.kind_of?(Array)
return ids.first if expects_array && ids.first.empty?
ids = ids.flatten.compact.uniq
case ids.size
when 0
raise RecordNotFound, "Couldn't find #{name} without an ID"
when 1
result = find_one(ids.first, options)
expects_array ? [ result ] : result
else
find_some(ids, options)
end
end
|
.find_initial(options) ⇒ Object
269
270
271
272
273
274
275
276
277
|
# File 'lib/hyper_record.rb', line 269
def find_initial(options)
options.update(:limit => 1)
if options[:scan_spec]
find_by_options(options)
else
find_by_options(options).first
end
end
|
.find_one(id, options) ⇒ Object
396
397
398
399
400
401
402
403
404
405
406
|
# File 'lib/hyper_record.rb', line 396
def find_one(id, options)
return nil if id.blank?
options[:row_keys] = [id.to_s]
if result = find_initial(options)
result
else
raise ::ActiveRecord::RecordNotFound, "Couldn't find #{name} with ID=#{id}"
end
end
|
.find_some(ids, options) ⇒ Object
408
409
410
411
|
# File 'lib/hyper_record.rb', line 408
def find_some(ids, options)
options[:row_keys] = [ids.map{|i| i.to_s}]
find_by_options(options)
end
|
.find_to_scan_spec(*args) ⇒ Object
213
214
215
216
217
218
|
# File 'lib/hyper_record.rb', line 213
def find_to_scan_spec(*args)
options = args.
options[:scan_spec] = true
args << options
find(*args)
end
|
.find_with_scanner(*args, &block) ⇒ Object
220
221
222
223
|
# File 'lib/hyper_record.rb', line 220
def find_with_scanner(*args, &block)
scan_spec = find_to_scan_spec(*args)
with_scanner(scan_spec, &block)
end
|
.flush_mutator(mutator) ⇒ Object
496
497
498
|
# File 'lib/hyper_record.rb', line 496
def flush_mutator(mutator)
self.connection.flush_mutator(mutator)
end
|
.open_mutator ⇒ Object
Return an open mutator on this table.
488
489
490
|
# File 'lib/hyper_record.rb', line 488
def open_mutator
self.connection.open_mutator(table_name)
end
|
.open_scanner(scan_spec) ⇒ Object
501
502
503
|
# File 'lib/hyper_record.rb', line 501
def open_scanner(scan_spec)
self.connection.open_scanner(self.table_name, scan_spec)
end
|
.primary_key ⇒ Object
Returns the primary key field for a table. In Hypertable, a single row key exists for each row. The row key is referred to as ROW in HQL, so we’ll refer to it the same way here.
424
425
426
|
# File 'lib/hyper_record.rb', line 424
def primary_key
"ROW"
end
|
.qualified?(column_name) ⇒ Boolean
446
447
448
|
# File 'lib/hyper_record.rb', line 446
def qualified?(column_name)
@qualified_columns.map{|c| c[:column_name]}.include?(column_name.to_sym)
end
|
.qualified_column(*attrs) ⇒ Object
473
474
475
476
477
478
479
480
481
482
483
|
# File 'lib/hyper_record.rb', line 473
def qualified_column(*attrs)
@qualified_columns ||= []
name = attrs.shift
qualifiers = attrs.shift
qualifiers = qualifiers.symbolize_keys[:qualifiers] if qualifiers
@qualified_columns << {
:column_name => name,
:qualifiers => qualifiers || []
}
end
|
.qualified_column_names_without_row_key ⇒ Object
460
461
462
463
464
465
466
467
468
469
|
# File 'lib/hyper_record.rb', line 460
def qualified_column_names_without_row_key
cols = column_families_without_row_key.map{|c| c.name}
for qc in @qualified_columns
cols.delete(qc[:column_name].to_s)
for qualifier in qc[:qualifiers]
cols << "#{qc[:column_name]}:#{qualifier}"
end
end
cols
end
|
.quoted_column_names(attributes = attributes_with_quotes) ⇒ Object
450
451
452
453
454
|
# File 'lib/hyper_record.rb', line 450
def quoted_column_names(attributes=attributes_with_quotes)
attributes.keys.collect do |column_name|
self.class.connection.quote_column_name_for_table(column_name, table_name)
end
end
|
.set_default_options(options) ⇒ Object
279
280
281
282
283
284
285
286
287
|
# File 'lib/hyper_record.rb', line 279
def set_default_options(options)
options[:table_name] ||= table_name
options[:columns] ||= columns
options[:select] ||= qualified_column_names_without_row_key.map{|c|
connection.hypertable_column_name(c, table_name)
}
end
|
.table_exists?(name = table_name) ⇒ Boolean
413
414
415
|
# File 'lib/hyper_record.rb', line 413
def table_exists?(name=table_name)
connection.tables.include?(name)
end
|
.with_scanner(scan_spec, &block) ⇒ Object
509
510
511
|
# File 'lib/hyper_record.rb', line 509
def with_scanner(scan_spec, &block)
self.connection.with_scanner(self.table_name, scan_spec, &block)
end
|
.with_thrift_client ⇒ Object
530
531
532
|
# File 'lib/hyper_record.rb', line 530
def with_thrift_client
self.connection.with_thrift_client
end
|
Instance Method Details
#attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true) ⇒ Object
Returns a copy of the attributes hash where all the values have been safely quoted for insertion. Translated qualified columns from a Hash value in Ruby to a flat list of attributes.
>
"ROW" => "page_1",
"name" => "name",
"url" => "http://www.icanhascheezburger.com"
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# File 'lib/hyper_record.rb', line 111
def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true)
quoted = attributes.inject({}) do |quoted, (name, value)|
if column = column_for_attribute(name)
if column.is_a?(ConnectionAdapters::QualifiedColumn) and value.is_a?(Hash)
value.keys.each{|k|
quoted[self.class.connection.qualified_column_name(column.name, k)] = quote_value(value[k], column)
}
else
quoted[name] = quote_value(value, column) unless !include_primary_key && column.primary
end
end
quoted
end
include_readonly_attributes ? quoted : remove_readonly_attributes(quoted)
end
|
#create(mutator = nil) ⇒ Object
43
44
45
46
47
48
|
# File 'lib/hyper_record.rb', line 43
def create(mutator=nil)
write_quoted_attributes(attributes_with_quotes(false, false),
self.class.table_name, mutator)
@new_record = false
self.attributes[self.class.primary_key]
end
|
#create_or_update_with_mutator(mutator) ⇒ Object
58
59
60
61
62
|
# File 'lib/hyper_record.rb', line 58
def create_or_update_with_mutator(mutator)
raise ReadOnlyRecord if readonly?
result = new_record? ? create(mutator) : update(mutator)
result != false
end
|
#decrement(attribute, by = 1) ⇒ Object
94
95
96
|
# File 'lib/hyper_record.rb', line 94
def decrement(attribute, by=1)
increment(attribute, -by)
end
|
#decrement!(attribute, by = 1) ⇒ Object
98
99
100
|
# File 'lib/hyper_record.rb', line 98
def decrement!(attribute, by=1)
increment!(attribute, -by)
end
|
#delete_cells(cells, table = self.class.table_name) ⇒ Object
Delete an array of cells from Hypertable cells is an array of cell keys [[“row”, “column”], …]
163
164
165
166
167
168
169
170
171
172
173
174
|
# File 'lib/hyper_record.rb', line 163
def delete_cells(cells, table=self.class.table_name)
if HyperBase.log_calls
msg = [
"Deleting #{cells.length} cells from #{table} table",
cells.map{|c| [ c[0], c[1] ].compact.join("\t")}
].join("\n")
RAILS_DEFAULT_LOGGER.info(msg)
end
connection.delete_cells(table, cells)
end
|
#delete_rows(row_keys, table = self.class.table_name) ⇒ Object
Delete an array of rows from Hypertable rows is an array of row keys [“row1”, “row2”, …]
178
179
180
|
# File 'lib/hyper_record.rb', line 178
def delete_rows(row_keys, table=self.class.table_name)
connection.delete_rows(table, cells)
end
|
#destroy ⇒ Object
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
# File 'lib/hyper_record.rb', line 64
def destroy
for reflection_key in self.class.reflections.keys
case self.class.reflections[reflection_key].macro
when :has_and_belongs_to_many
cells_to_delete = []
for row_key in self.send(self.class.reflections[reflection_key].association_foreign_key).keys
cells_to_delete << connection.cell_native_array(row_key, self.class.reflections[reflection_key].primary_key_name, self.ROW)
end
self.delete_cells(cells_to_delete, self.class.reflections[reflection_key].klass.table_name)
end
end
self.class.connection.delete_rows(self.class.table_name, [self.ROW])
end
|
#increment(attribute, by = 1) ⇒ Object
83
84
85
86
87
|
# File 'lib/hyper_record.rb', line 83
def increment(attribute, by=1)
self[attribute] = self[attribute].to_i
self[attribute] += by
self
end
|
#increment!(attribute, by = 1) ⇒ Object
89
90
91
92
|
# File 'lib/hyper_record.rb', line 89
def increment!(attribute, by=1)
increment(attribute, by)
self.save
end
|
#quoted_attributes_to_cells(quoted_attrs, table = self.class.table_name) ⇒ Object
Translates the output of attributes_with_quotes into an array of cells suitable for writing into Hypertable (through the write_cells method). Data format is native array format for cells. [
["row_key", "column_family", "column_qualifier", "value"],
]
133
134
135
136
137
138
139
140
141
|
# File 'lib/hyper_record.rb', line 133
def quoted_attributes_to_cells(quoted_attrs, table=self.class.table_name)
cells = []
pk = self.attributes[self.class.primary_key]
quoted_attrs.keys.each{|key|
name, qualifier = connection.hypertable_column_name(key, table).split(':', 2)
cells << connection.cell_native_array(pk, name, qualifier, quoted_attrs[key])
}
cells
end
|
#save_with_mutator(mutator) ⇒ Object
50
51
52
|
# File 'lib/hyper_record.rb', line 50
def save_with_mutator(mutator)
create_or_update_with_mutator(mutator)
end
|
#save_with_mutator!(mutator) ⇒ Object
54
55
56
|
# File 'lib/hyper_record.rb', line 54
def save_with_mutator!(mutator)
create_or_update_with_mutator(mutator) || raise(RecordNotSaved)
end
|
#update(mutator = nil) ⇒ Object
37
38
39
40
41
|
# File 'lib/hyper_record.rb', line 37
def update(mutator=nil)
write_quoted_attributes(attributes_with_quotes(false, false),
self.class.table_name, mutator)
true
end
|
#write_cells(cells, table = self.class.table_name, mutator = nil) ⇒ Object
Write an array of cells to Hypertable
148
149
150
151
152
153
154
155
156
157
158
159
|
# File 'lib/hyper_record.rb', line 148
def write_cells(cells, table=self.class.table_name, mutator=nil)
if HyperBase.log_calls
msg = [
"Writing #{cells.length} cells to #{table} table",
cells.map{|c| [c[0], c[1], c[2], c[3].to_s.first(20)].compact.join("\t")}
].join("\n")
RAILS_DEFAULT_LOGGER.info(msg)
end
connection.write_cells(table, cells, mutator)
end
|
#write_quoted_attributes(quoted_attrs, table = self.class.table_name, mutator = nil) ⇒ Object
143
144
145
|
# File 'lib/hyper_record.rb', line 143
def write_quoted_attributes(quoted_attrs, table=self.class.table_name, mutator=nil)
write_cells(quoted_attributes_to_cells(quoted_attrs, table), table, mutator)
end
|