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



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

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



106
107
108
# File 'lib/rubyrep/proxy_connection.rb', line 106

def config
  @config
end

#connectionObject

The database connection



103
104
105
# File 'lib/rubyrep/proxy_connection.rb', line 103

def connection
  @connection
end

#cursorsObject

Returns a Hash of currently registerred cursors



129
130
131
# File 'lib/rubyrep/proxy_connection.rb', line 129

def cursors
  @cursors
end

#manual_primary_keysObject

A hash of manually overwritten primary keys:

  • key: table_name

  • value: array of primary key names



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

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


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

def primary_key_names_cache
  @primary_key_names_cache
end

#table_column_namesObject

Hash of table_name => array of column names pairs.



135
136
137
# File 'lib/rubyrep/proxy_connection.rb', line 135

def table_column_names
  @table_column_names
end

#table_columnsObject

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



132
133
134
# File 'lib/rubyrep/proxy_connection.rb', line 132

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.



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

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.


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

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)



165
166
167
# File 'lib/rubyrep/proxy_connection.rb', line 165

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.



427
428
429
# File 'lib/rubyrep/proxy_connection.rb', line 427

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

#destroyObject

Destroys the session



236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/rubyrep/proxy_connection.rb', line 236

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



273
274
275
276
# File 'lib/rubyrep/proxy_connection.rb', line 273

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.



379
380
381
# File 'lib/rubyrep/proxy_connection.rb', line 379

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



150
151
152
153
154
155
156
157
158
159
160
# File 'lib/rubyrep/proxy_connection.rb', line 150

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.



252
253
254
255
256
257
258
259
# File 'lib/rubyrep/proxy_connection.rb', line 252

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.quote value, table_columns[table][column]
end

#save_cursor(cursor) ⇒ Object

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



175
176
177
# File 'lib/rubyrep/proxy_connection.rb', line 175

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

  • :type_cast: Unless explicitely disabled with false, build type casting cursor around result.

  • :table: Name of the table from which to read data. Required unless type casting is disabled.

  • 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.



196
197
198
199
200
201
202
# File 'lib/rubyrep/proxy_connection.rb', line 196

def select_cursor(options)
  cursor = ResultFetcher.new(self, options)
  unless options[:type_cast] == false
    cursor = TypeCastingCursor.new(self, options[:table], cursor)
  end
  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).



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

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).



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

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.)



415
416
417
418
419
420
421
# File 'lib/rubyrep/proxy_connection.rb', line 415

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.



366
367
368
369
370
371
372
373
374
375
# File 'lib/rubyrep/proxy_connection.rb', line 366

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.


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
# File 'lib/rubyrep/proxy_connection.rb', line 327

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.



389
390
391
392
393
394
395
396
397
398
399
# File 'lib/rubyrep/proxy_connection.rb', line 389

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.



408
409
410
# File 'lib/rubyrep/proxy_connection.rb', line 408

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