Class: RR::ProxyConnection

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
DRbUndumped
Defined in:
lib/rubyrep/proxy_connection.rb

Overview

This class represents a remote activerecord database connection. Normally created by DatabaseProxy

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ ProxyConnection

Create a session on the proxy side according to provided configuration hash. config is a hash as described by ActiveRecord::Base#establish_connection



239
240
241
242
243
# File 'lib/rubyrep/proxy_connection.rb', line 239

def initialize(config)
  self.connection = ConnectionExtenders.db_connect config
  self.config = config
  self.manual_primary_keys = {}
end

Instance Attribute Details

#configObject

A hash as described by ActiveRecord::Base#establish_connection



124
125
126
# File 'lib/rubyrep/proxy_connection.rb', line 124

def config
  @config
end

#connectionObject

The database connection



121
122
123
# File 'lib/rubyrep/proxy_connection.rb', line 121

def connection
  @connection
end

#cursorsObject

Returns a Hash of currently registerred cursors



147
148
149
# File 'lib/rubyrep/proxy_connection.rb', line 147

def cursors
  @cursors
end

#manual_primary_keysObject

A hash of manually overwritten primary keys:

  • key: table_name

  • value: array of primary key names



158
159
160
# File 'lib/rubyrep/proxy_connection.rb', line 158

def manual_primary_keys
  @manual_primary_keys
end

#primary_key_names_cacheObject

Caching the primary keys. This is a hash with

* key: table name
* value: array of primary key names


141
142
143
# File 'lib/rubyrep/proxy_connection.rb', line 141

def primary_key_names_cache
  @primary_key_names_cache
end

#table_column_namesObject

Hash of table_name => array of column names pairs.



153
154
155
# File 'lib/rubyrep/proxy_connection.rb', line 153

def table_column_names
  @table_column_names
end

#table_columnsObject

2-level Hash of table_name => column_name => Column objects.



150
151
152
# File 'lib/rubyrep/proxy_connection.rb', line 150

def table_columns
  @table_columns
end

Instance Method Details

#column_names(table) ⇒ Object

Returns an array of column names of the given table name. The array is ordered in the sequence as returned by the database. The result is cached for higher speed.



291
292
293
294
295
296
297
# File 'lib/rubyrep/proxy_connection.rb', line 291

def column_names(table)
  self.table_column_names ||= {}
  unless table_column_names.include? table
    table_column_names[table] = columns(table).map {|c| c.name}
  end
  table_column_names[table]
end

#create_cursor(cursor_class, table, options = {}) ⇒ Object

Create a cursor for the given table.

* +cursor_class+: should specify the Cursor class (e. g. ProxyBlockCursor or ProxyRowCursor).
* +table+: name of the table 
* +options+: An option hash that is used to construct the SQL query. See ProxyCursor#construct_query for details.


275
276
277
278
279
280
# File 'lib/rubyrep/proxy_connection.rb', line 275

def create_cursor(cursor_class, table, options = {})
  cursor = cursor_class.new self, table
  cursor.prepare_fetch options
  save_cursor cursor
  cursor
end

#create_table(*params) ⇒ Object

Creates a table Call forwarded to ActiveRecord::ConnectionAdapters::SchemaStatements#create_table Provides an empty block (to prevent DRB from calling back the client)



183
184
185
# File 'lib/rubyrep/proxy_connection.rb', line 183

def create_table(*params)
  connection.create_table(*params) {}
end

#delete_record(table, values) ⇒ Object

Deletes the specified record from the named table. values is a hash of column_name => value pairs. (Only the primary key values will be used and must be included in the hash.) Returns the number of deleted records.



437
438
439
# File 'lib/rubyrep/proxy_connection.rb', line 437

def delete_record(table, values)
  delete table_delete_query(table, values)
end

#destroyObject

Destroys the session



246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/rubyrep/proxy_connection.rb', line 246

def destroy
  cursors.each_key do |cursor|
    cursor.destroy
  end
  cursors.clear

  if connection.log_subscriber
    ActiveSupport::Notifications.notifier.unsubscribe connection.log_subscriber
    connection.log_subscriber = nil
  end

  self.connection.disconnect!
end

#destroy_cursor(cursor) ⇒ Object

Destroys the provided cursor and removes it from the register



283
284
285
286
# File 'lib/rubyrep/proxy_connection.rb', line 283

def destroy_cursor(cursor)
  cursor.destroy
  cursors.delete cursor
end

#insert_record(table, values) ⇒ Object

Inserts the specified records into the named table. values is a hash of column_name => value pairs.



389
390
391
# File 'lib/rubyrep/proxy_connection.rb', line 389

def insert_record(table, values)
  execute table_insert_query(table, values)
end

#primary_key_names(table_name, options = {}) ⇒ Object

Returns an array of primary key names for the given table_name. Caches the result for future calls. Allows manual overwrites through the Configuration options :primary_key_names or :primary_key_only_limit.

Parameters:

  • table_name: name of the table

  • options: An option hash with the following valid options:

    • :raw: if true, than don’t use manual overwrites and don’t cache



168
169
170
171
172
173
174
175
176
177
178
# File 'lib/rubyrep/proxy_connection.rb', line 168

def primary_key_names(table_name, options = {})
  return connection.primary_key_names(table_name) if options[:raw]
  
  self.primary_key_names_cache ||= {}
  result = primary_key_names_cache[table_name]
  unless result
    result = manual_primary_keys[table_name] || connection.primary_key_names(table_name)
    primary_key_names_cache[table_name] = result
  end
  result
end

#quote_value(table, column, value) ⇒ Object

Quotes the given value. It is assumed that the value belongs to the specified column name and table name. Caches the column objects for higher speed.



262
263
264
265
266
267
268
269
# File 'lib/rubyrep/proxy_connection.rb', line 262

def quote_value(table, column, value)
  self.table_columns ||= {}
  unless table_columns.include? table
    table_columns[table] = {}
    columns(table).each {|c| table_columns[table][c.name] = c}
  end
  connection.column_aware_quote value, table_columns[table][column.to_s]
end

#save_cursor(cursor) ⇒ Object

Store a cursor in the register to protect it from the garbage collector.



193
194
195
# File 'lib/rubyrep/proxy_connection.rb', line 193

def save_cursor(cursor)
  cursors[cursor] = cursor
end

#select_cursor(options) ⇒ Object

Returns a cusor as produced by the #select_cursor method of the connection extenders.

Two modes of operation: Either

  • execute the specified query (takes precedense) OR

  • first build the query based on options forwarded to #table_select_query

options is a hash with

  • :query: executes the given query

  • further options as taken by #table_select_query to build the query

  • :row_buffer_size: Integer controlling how many rows a read into memory at one time.



208
209
210
211
212
# File 'lib/rubyrep/proxy_connection.rb', line 208

def select_cursor(options)
  cursor = ResultFetcher.new(self, options)
  cursor = TypeCastingCursor.new(self, options[:table], cursor)
  cursor
end

#select_record(options) ⇒ Object

Reads the designated record from the database. Refer to #select_cursor for details parameter description. Returns the first matching row (column_name => value hash or nil).



217
218
219
220
221
222
# File 'lib/rubyrep/proxy_connection.rb', line 217

def select_record(options)
  cursor = select_cursor({:row_buffer_size => 1}.merge(options))
  row = cursor.next? ? cursor.next_row : nil
  cursor.clear
  row
end

#select_records(options) ⇒ Object

Reads the designated records from the database. Refer to #select_cursor for details parameter description. Returns an array of matching rows (column_name => value hashes).



227
228
229
230
231
232
233
234
235
# File 'lib/rubyrep/proxy_connection.rb', line 227

def select_records(options)
  cursor = select_cursor(options)
  rows = []
  while cursor.next?
    rows << cursor.next_row
  end
  cursor.clear
  rows
end

#table_delete_query(table, values) ⇒ Object

Returns an SQL delete query for the given table and values values is a hash of column_name => value pairs. (Only the primary key values will be used and must be included in the hash.)



425
426
427
428
429
430
431
# File 'lib/rubyrep/proxy_connection.rb', line 425

def table_delete_query(table, values)
  query = "delete from #{quote_table_name(table)}"
  query << " where (" << quote_key_list(table) << ") = ("
  query << primary_key_names(table).map do |key|
    quote_value(table, key, values[key])
  end.join(', ') << ")"
end

#table_insert_query(table, values) ⇒ Object

Returns an SQL insert query for the given table and values. values is a hash of column_name => value pairs.



376
377
378
379
380
381
382
383
384
385
# File 'lib/rubyrep/proxy_connection.rb', line 376

def table_insert_query(table, values)
  query = "insert into #{quote_table_name(table)}"
  query << '(' << values.keys.map do |column_name|
    quote_column_name(column_name)
  end.join(', ') << ') '
  query << 'values(' << values.map do |column_name, value|
    quote_value(table, column_name, value)
  end.join(', ') << ')'
  query
end

#table_select_query(table, options = {}) ⇒ Object

Returns an SQL query string for the given table based on the provided options. options is a hash that can contain any of the following:

* :+from+: nil OR the hash of primary key => value pairs designating the start of the selection
* :+exclude_starting_row+: if true, do not include the row specified by :+from+
* :+to+: nil OR the hash of primary key => value pairs designating the end of the selection
* :+row_keys+: an array of primary key => value hashes specify the target rows.


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
366
367
368
369
370
371
372
# File 'lib/rubyrep/proxy_connection.rb', line 337

def table_select_query(table, options = {})
  query = "select #{quote_column_list(table)}"
  query << " from #{quote_table_name(table)}"
  query << " where" if [:from, :to, :row_keys].any? {|key| options.include? key}
  first_condition = true
  if options[:from]
    first_condition = false
    matching_condition = options[:exclude_starting_row] ? '>' : '>='
    query << row_condition(table, options[:from], matching_condition)
  end
  if options[:to]
    query << ' and' unless first_condition
    first_condition = false
    query << row_condition(table, options[:to], '<=')
  end
  if options[:row_keys]
    query << ' and' unless first_condition
    if options[:row_keys].empty?
      query << ' false'
    else
      query << ' (' << quote_key_list(table) << ') in ('
      first_key = true
      options[:row_keys].each do |row|
        query << ', ' unless first_key
        first_key = false
        query << '(' << primary_key_names(table).map do |key|
          quote_value(table, key, row[key])
        end.join(', ') << ')'
      end
      query << ')'
    end
  end
  query << " order by #{quote_key_list(table)}"

  query
end

#table_update_query(table, values, org_key = nil) ⇒ Object

Returns an SQL update query.

  • table: name of the target table

  • values: a hash of column_name => value pairs

  • org_key: A hash of column_name => value pairs. If nil, use the key specified by values instead.



399
400
401
402
403
404
405
406
407
408
409
# File 'lib/rubyrep/proxy_connection.rb', line 399

def table_update_query(table, values, org_key = nil)
  org_key ||= values
  query = "update #{quote_table_name(table)} set "
  query << values.map do |column_name, value|
    "#{quote_column_name(column_name)} = #{quote_value(table, column_name, value)}"
  end.join(', ')
  query << " where (" << quote_key_list(table) << ") = ("
  query << primary_key_names(table).map do |key|
    quote_value(table, key, org_key[key])
  end.join(', ') << ")"
end

#update_record(table, values, org_key = nil) ⇒ Object

Updates the specified records of the specified table.

  • table: name of the target table

  • values: a hash of column_name => value pairs.

  • org_key: A hash of column_name => value pairs. If nil, use the key specified by values instead.

Returns the number of modified records.



418
419
420
# File 'lib/rubyrep/proxy_connection.rb', line 418

def update_record(table, values, org_key = nil)
  update table_update_query(table, values, org_key)
end