# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 447 def primary_key(table_name) # n.b. active record does not support composite primary keys! row = exec_query(<<-eosql, 'SCHEMA', [config[:schema], table_name.to_s]).rows.first SELECT indexfields.field as field_name FROM system.indexfields AS indexfields WHERE indexfields.schema = ? AND indexfields.tablename = ? eosql row && row.first.downcase end
class ActiveRecord::ConnectionAdapters::NuoDBAdapter
Constants
- CONNECTION_NOT_ESTABLISHED_MESSAGES
- LOST_CONNECTION_MESSAGES
EXCEPTION TRANSLATION ==================================
Attributes
Public Class Methods
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 255 def initialize(connection, logger, pool, config) super(connection, logger, pool) @visitor = Arel::Visitors::NuoDB.new self @config = config.clone # prefer to run with prepared statements unless otherwise specified if @config.fetch(:prepared_statements) { true } @visitor = Arel::Visitors::NuoDB.new self else @visitor = BindSubstitution.new self end connect! end
Public Instance Methods
ADAPTER NAME ===========================================
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 272 def adapter_name 'NuoDB' end
Carlos Added Begins
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 503 def add_column(table_name, column_name, type, options = {}) clear_cache! #Stored procedure not supported #add_column_sql = "CREATE PROCEDURE PR1 BEGIN IF NOT EXISTS((SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() # AND COLUMN_NAME=#{quote_column_name(column_name)} AND TABLE_NAME=#{quote_table_name(table_name)})) THEN ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{type.to_s} END IF" if column_exists?(table_name, column_name) == false add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{type.to_s}" add_column_options!(add_column_sql, options) execute(add_column_sql) end end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 515 def add_index(table_name, column_name, options = {}) index_name, index_type, index_columns = add_index_options(table_name, column_name, options) if okay_index(table_name, column_name, options = {}) == true execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})" end end
Begins the transaction (and turns off auto-committing).
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 821 def begin_db_transaction() log('begin transaction', nil) { raw_connection.autocommit = false if raw_connection.autocommit? } end
Bug: (4) methods, see: tools/jira/browse/DB-2389
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 471 def change_column(table_name, column_name, type, options = {}) raise NotImplementedError, "change_column is not implemented" #execute("ALTER TABLE #{quote_table_name(table_name)} #{change_column_sql(table_name, column_name, type, options)}") end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 476 def change_column_default(table_name, column_name, default) raise NotImplementedError, "change_column_default is not implemented" #column = column_for(table_name, column_name) #change_column table_name, column_name, column.sql_type, :default => default end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 482 def change_column_null(table_name, column_name, null, default = nil) raise NotImplementedError, "change_column_null is not implemented" #column = column_for(table_name, column_name) #unless null || default.nil? # execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") #end #change_column table_name, column_name, column.sql_type, :null => null end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 391 def clear_cache! @statements.clear end
Carlos Added
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 542 def column_exists?(table_name, column_name, type = nil, options = {}) begin execute("SELECT #{quote_column_name(column_name)} FROM #{quote_table_name(table_name)}") return true rescue return false end end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 630 def columns(table_name, name = nil) # the following query returns something like this: # # INDEXNAME TABLENAME NON_UNIQUE FIELD LENGTH # ---------------------- --------- ---------- --------- ------ # COMPANIES..PRIMARY_KEY COMPANIES 0 ID 4 # COMPANY_INDEX COMPANIES 1 FIRM_ID 4 # COMPANY_INDEX COMPANIES 1 TYPE 255 # COMPANY_INDEX COMPANIES 1 RATING 4 # COMPANY_INDEX COMPANIES 1 RUBY_TYPE 255 result = exec_query(<<-eosql, 'SCHEMA', [config[:schema], table_name.to_s]) SELECT fields.field as name, fields.defaultvalue as default_value, datatypes.name as data_type, fields.length as length, fields.scale as scale, fields.precision as precision, fields.flags as flags FROM system.fields AS fields, system.datatypes AS datatypes WHERE schema = ? AND tablename = ? AND datatypes.id = fields.datatype ORDER BY fields.fieldposition eosql columns = [] result.map do |row| row.symbolize_keys! columns << NuoDBColumn.new(row[:name].downcase, row[:default_value], row[:data_type], row[:flags].to_i & 1 == 0, row[:length], row[:scale], row[:precision]) end columns end
Commits the transaction (and turns on auto-committing).
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 828 def commit_db_transaction() log('commit transaction', nil) { raw_connection.autocommit = true unless raw_connection.autocommit? raw_connection.commit } end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 375 def connect! @connection = ::NuoDB::Connection.new(config) @statements = StatementPool.new(@connection, @config.fetch(:statement_limit) { 1000 }) @quoted_column_names, @quoted_table_names = {}, {} end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 923 def convert_results(results) ActiveRecord::Result.new(column_names(results), results.rows) end
SAVEPOINT SUPPORT ======================================
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 397 def create_savepoint execute("SAVEPOINT #{current_savepoint_name}") end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 844 def default_sequence_name(table, column) result = exec_query(<<-eosql, 'SCHEMA', [table.to_s, column.to_s]) SELECT generator_sequence FROM system.fields WHERE tablename='#{table}' AND field='#{column}' eosql result.rows.first.first rescue ActiveRecord::StatementInvalid "#{table}$#{column}" end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 381 def disconnect! super clear_cache! raw_connection.disconnect rescue nil end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 871 def exec_delete(sql, name, binds) exec_query(sql, name, binds.map { |col, val| type_cast(val, col) }) end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 863 def exec_insert(sql, name, binds) exec_query sql, name, binds.map { |col, val| type_cast(val, col) }, true end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 875 def exec_query(sql, name = 'SQL', binds = [], get_generated_keys = false) log(sql, name, binds) do if binds.empty? cache = statements[process_id] ||= { :stmt => raw_connection.statement } stmt = cache[:stmt] results = nil if stmt.execute(sql) results = convert_results stmt.results end if get_generated_keys generated_keys_result = stmt.generated_keys if generated_keys_result.nil? || generated_keys_result.rows.empty? @last_inserted_id = nil else @last_inserted_id = generated_keys_result.rows.last[0] end end results else cache = statements[sql] ||= { :stmt => raw_connection.prepare(sql) } stmt = cache[:stmt] results = nil stmt.bind_params binds if stmt.execute results = convert_results stmt.results end if get_generated_keys generated_keys_result = stmt.generated_keys if generated_keys_result.nil? || generated_keys_result.rows.empty? @last_inserted_id = nil else @last_inserted_id = generated_keys_result.rows.last[0] end end results end end end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 867 def exec_update(sql, name, binds) exec_query(sql, name, binds, true) end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 853 def execute(sql, name = 'SQL') log(sql, name) do cache = statements[process_id] ||= { :stmt => raw_connection.statement } stmt = cache[:stmt] stmt.execute(sql) end end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 314 def explain(arel, binds = []) sql = "EXPLAIN #{to_sql(arel, binds.dup)}" start = Time.now result = exec_query(sql, 'EXPLAIN', binds) elapsed = Time.now - start ExplainPrettyPrinter.new.pp(result, elapsed) end
Returns an array of indexes for the given table. Skip primary keys.
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 583 def indexes(table_name, name = nil) # the following query returns something like this: # # INDEXNAME TABLENAME NON_UNIQUE FIELD LENGTH # ---------------------- --------- ---------- --------- ------ # COMPANIES..PRIMARY_KEY COMPANIES 0 ID 4 # COMPANY_INDEX COMPANIES 1 FIRM_ID 4 # COMPANY_INDEX COMPANIES 1 TYPE 255 # COMPANY_INDEX COMPANIES 1 RATING 4 # COMPANY_INDEX COMPANIES 1 RUBY_TYPE 255 result = exec_query(<<-eosql, 'SCHEMA', [config[:schema], table_name.to_s]) SELECT indexes.indexname as index_name, indexes.tablename as table_name, CASE indexes.indextype WHEN 2 THEN 1 ELSE 0 END AS non_unique, indexfields.field as field_name, fields.length as field_length FROM system.indexes AS indexes, system.indexfields AS indexfields, system.fields AS fields WHERE indexes.schema = ? AND indexes.tablename = ? AND indexes.indexname = indexfields.indexname AND indexfields.field = fields.field AND indexfields.schema = fields.schema AND indexfields.tablename = fields.tablename eosql indexes = [] current_index = nil result.map do |row| row.symbolize_keys! #Carlos Added .downcase! index_name = row[:index_name].downcase! if current_index != index_name next if !!(/PRIMARY/ =~ index_name) current_index = index_name table_name = row[:table_name] is_unique = row[:non_unique].to_i == 1 indexes << IndexDefinition.new(table_name, index_name, is_unique, [], [], []) end indexes.last.columns << row[:field_name] unless row[:field_name].nil? indexes.last.lengths << row[:field_length] unless row[:field_length].nil? end indexes end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 927 def last_inserted_id(result) @last_inserted_id end
jruby version – no original
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 692 def modify_types(tp) tp[:primary_key] = 'int not null generated always primary key' tp[:boolean] = {:name => 'boolean'} tp[:date] = {:name => 'date', :limit => nil} tp[:datetime] = {:name => 'timestamp', :limit => nil} tp[:decimal] = {:name => 'decimal'} tp[:integer] = {:name => 'int', :limit => 4} tp[:string] = {:name => 'string'} tp[:time] = {:name => 'time', :limit => nil} tp[:timestamp] = {:name => 'timestamp', :limit => nil} tp end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 669 def native_database_types { # generic rails types... :binary => {:name => 'binary'}, :boolean => {:name => 'boolean'}, :date => {:name => 'date'}, :datetime => {:name => 'timestamp'}, :decimal => {:name => 'decimal'}, :float => {:name => 'float', :limit => 8}, :integer => {:name => 'integer', :limit => 4}, :primary_key => 'int not null generated by default as identity primary key', :string => {:name => 'varchar', :limit => 255}, :text => {:name => 'string'}, :time => {:name => 'time'}, :timestamp => {:name => 'timestamp'}, # nuodb specific types... :char => {:name => 'char'}, :numeric => {:name => 'numeric(20)'}, :binarystring => {:name => 'varchar', :limit => 255} } end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 522 def okay_index(table_name, column_name, options = {}) begin execute("CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})") return true rescue return false end end
def select_values(sql, name = nil) exec_query
(sql, name).values end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 812 def outside_transaction? nil end
SCHEMA DEFINITIONS #####################################
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 245 def process_id Process.pid end
QUOTING ################################################
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 769 def quote_column_name(name) @quoted_column_names[name] ||= "`#{name.to_s.gsub('`', '``')}`" end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 773 def quote_table_name(name) @quoted_table_names[name] ||= quote_column_name(name).gsub('.', '`.`') end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 790 def quoted_date(value) if value.acts_like?(:time) zone_conversion_method = :getutc if value.respond_to?(zone_conversion_method) value = value.send(zone_conversion_method) end end value.to_s(:db) end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 786 def quoted_false "'false'" end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 782 def quoted_true "'true'" end
CONNECTION MANAGEMENT ==================================
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 369 def reconnect! disconnect! connect! super end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 405 def release_savepoint execute("RELEASE SAVEPOINT #{current_savepoint_name}") end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 491 def rename_column(table_name, column_name, new_column_name) raise NotImplementedError, "rename_column is not implemented" #execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_sql(table_name, column_name, new_column_name)}") end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 537 def rename_index(table_name, old_name, new_name) execute("ALTER INDEX #{quote_column_name(old_name)} RENAME TO #{quote_table_name(new_name)}") end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 496 def rename_table(table_name, new_name) raise NotImplementedError, "rename_table is not implemented" #execute("RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}") end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 387 def reset! reconnect! end
Rolls back the transaction (and turns on auto-committing). Must be done if the transaction block raises an exception or returns false.
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 837 def rollback_db_transaction() log('rollback transaction', nil) { raw_connection.autocommit = true unless raw_connection.autocommit? raw_connection.rollback } end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 401 def rollback_to_savepoint execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}") end
DATABASE STATEMENTS ####################################
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 804 def select_rows(sql, name = nil) exec_query(sql, name).rows end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 294 def supports_bulk_alter? false end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 286 def supports_count_distinct? true end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 290 def supports_ddl_transactions? true end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 310 def supports_explain? true end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 302 def supports_index_sort_order? true end
FEATURES ===============================================
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 278 def supports_migrations? true end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 306 def supports_partial_index? false end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 282 def supports_primary_key? true end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 298 def supports_savepoints? true end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 816 def supports_statement_cache? true end
ENDS
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 553 def table_exists?(table_name) return false unless table_name table_name = table_name.to_s.downcase schema, table = table_name.split('.', 2) unless table table = schema schema = nil end tables('SCHEMA', schema).include? table end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 567 def tables(name = 'SCHEMA', schema = nil) result = exec_query(<<-eosql, name, [schema || config[:schema]]) SELECT tablename FROM system.tables WHERE schema = ? eosql result.inject([]) do |tables, row| row.symbolize_keys! tables << row[:tablename].downcase end end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 777 def type_cast(value, column) return super unless value == true || value == false value ? true : false end
jruby version maps logical rails types to nuodb-specific data types.
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 707 def type_to_sql(type, limit = nil, precision = nil, scale = nil) case type.to_s when 'integer' return 'integer' unless limit case limit when 1..2 'smallint' when 3..4 'integer' when 5..8 'bigint' else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.") end when 'timestamp' column_type_sql = 'timestamp' unless precision.nil? case precision when 0..9 column_type_sql << "(#{precision})" else nil end end column_type_sql when 'time' column_type_sql = 'time' unless precision.nil? case precision when 0..9 column_type_sql << "(#{precision})" else nil end end column_type_sql else super end end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 461 def version self.class::VERSION end
Protected Instance Methods
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 421 def connection_not_established_messages CONNECTION_NOT_ESTABLISHED_MESSAGES end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 415 def lost_connection_messages LOST_CONNECTION_MESSAGES end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 933 def select(sql, name = nil, binds = []) exec_query(sql, name, binds.map { |col, val| type_cast(val, col) }).to_a end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 425 def translate_exception(exception, message) case message when /duplicate value in unique index/i RecordNotUnique.new(message, exception) when /too few values specified in the value list/i # defaults to StatementInvalid, so we are okay, but just to be explicit... super when *lost_connection_messages LostConnection.new(message, exception) when *connection_not_established_messages ConnectionNotEstablished.new(message) #when /violates foreign key constraint/ # InvalidForeignKey.new(message, exception) else super end end
Private Instance Methods
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 939 def column_names (result) return [] if result.nil? result.columns.inject([]) do |array, column| array << column.name.downcase end end
# File lib/active_record/connection_adapters/nuodb_adapter.rb, line 750 def split_table_name(table) name_parts = table.split '.' case name_parts.length when 1 schema_name = config[:schema] table_name = name_parts[0] when 2 schema_name = name_parts[0] table_name = name_parts[1] else raise "Invalid table name: #{table}" end [schema_name, table_name] end