Class: RR::ProxyConnection

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

Overview

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

Constant Summary collapse

DEFAULT_ROW_BUFFER_SIZE =

default number of records that are read into memory at a time during select queries

1000

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



195
196
197
198
199
# File 'lib/rubyrep/proxy_connection.rb', line 195

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



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

def config
  @config
end

#connectionObject

The database connection



99
100
101
# File 'lib/rubyrep/proxy_connection.rb', line 99

def connection
  @connection
end

#cursorsObject

Returns a Hash of currently registerred cursors



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

def cursors
  @cursors
end

#manual_primary_keysObject

A hash of manually overwritten primary keys:

  • key: table_name

  • value: array of primary key names



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

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


119
120
121
# File 'lib/rubyrep/proxy_connection.rb', line 119

def primary_key_names_cache
  @primary_key_names_cache
end

#table_column_namesObject

Hash of table_name => array of column names pairs.



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

def table_column_names
  @table_column_names
end

#table_columnsObject

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



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

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.



249
250
251
252
253
254
255
# File 'lib/rubyrep/proxy_connection.rb', line 249

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.


233
234
235
236
237
238
# File 'lib/rubyrep/proxy_connection.rb', line 233

def create_cursor(cursor_class, table, options = {})
  cursor = cursor_class.new self, table
  cursor.prepare_fetch options
  save_cursor cursor
  cursor
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.)



393
394
395
# File 'lib/rubyrep/proxy_connection.rb', line 393

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

#destroyObject

Destroys the session



209
210
211
212
213
214
215
216
# File 'lib/rubyrep/proxy_connection.rb', line 209

def destroy
  self.connection.disconnect!
  
  cursors.each_key do |cursor|
    cursor.destroy
  end
  cursors.clear
end

#destroy_cursor(cursor) ⇒ Object

Destroys the provided cursor and removes it from the register



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

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.



347
348
349
# File 'lib/rubyrep/proxy_connection.rb', line 347

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



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/rubyrep/proxy_connection.rb', line 146

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.



220
221
222
223
224
225
226
227
# File 'lib/rubyrep/proxy_connection.rb', line 220

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

#refreshObject

Checks if the connection is still active and if not, reestablished it.



202
203
204
205
206
# File 'lib/rubyrep/proxy_connection.rb', line 202

def refresh
  unless self.connection.active?
    self.connection = ConnectionExtenders.db_connect config
  end
end

#save_cursor(cursor) ⇒ Object

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



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

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: if true, build a type casting cursor around the result

  • :table: name of the table from which to read data

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



185
186
187
188
189
190
191
# File 'lib/rubyrep/proxy_connection.rb', line 185

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



382
383
384
385
386
387
388
# File 'lib/rubyrep/proxy_connection.rb', line 382

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.



334
335
336
337
338
339
340
341
342
343
# File 'lib/rubyrep/proxy_connection.rb', line 334

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.


295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/rubyrep/proxy_connection.rb', line 295

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.



357
358
359
360
361
362
363
364
365
366
367
# File 'lib/rubyrep/proxy_connection.rb', line 357

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.



375
376
377
# File 'lib/rubyrep/proxy_connection.rb', line 375

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