Class: ActiveRecord::ConnectionAdapters::RubyfbAdapter
- Inherits:
-
AbstractAdapter
- Object
- AbstractAdapter
- ActiveRecord::ConnectionAdapters::RubyfbAdapter
- Defined in:
- lib/active_record/connection_adapters/rubyfb_adapter.rb
Overview
Usage Notes
Sequence (Generator) Names
The Firebird adapter supports the same approach adopted for the Oracle adapter. See ActiveRecord::Base#set_sequence_name for more details.
Note that in general there is no need to create a BEFORE INSERT trigger corresponding to a Firebird sequence generator when using ActiveRecord. In other words, you don’t have to try to make Firebird simulate an AUTO_INCREMENT or IDENTITY column. When saving a new record, ActiveRecord pre-fetches the next sequence value for the table and explicitly includes it in the INSERT statement. (Pre-fetching the next primary key value is the only reliable method for the Firebird adapter to report back the id after a successful insert.)
BOOLEAN Domain
Firebird 1.5 does not provide a native BOOLEAN type. But you can easily define a BOOLEAN domain for this purpose, e.g.:
CREATE DOMAIN D_BOOLEAN AS SMALLINT CHECK (VALUE IN (0, 1) OR VALUE IS NULL);
When the Firebird adapter encounters a column that is based on a domain that includes “BOOLEAN” in the domain name, it will attempt to treat the column as a BOOLEAN.
By default, the Firebird adapter will assume that the BOOLEAN domain is defined as above. This can be modified if needed. For example, if you have a legacy schema with the following BOOLEAN domain defined:
CREATE DOMAIN BOOLEAN AS CHAR(1) CHECK (VALUE IN ('T', 'F'));
…you can add the following lines to your environment.rb file:
ActiveRecord::ConnectionAdapters::RubyfbAdapter.boolean_domain[:true] = 'T'
ActiveRecord::ConnectionAdapters::RubyfbAdapter.boolean_domain[:false] = 'F'
Boolean columns are detected by name and domain name patterns configurable by:
ActiveRecord::ConnectionAdapters::RubyfbAdapter.boolean_domain[:domain_pattern], default = /boolean/i
ActiveRecord::ConnectionAdapters::RubyfbAdapter.boolean_domain[:name_pattern], default = /^is_/i
BLOB Elements
The Firebird adapter currently provides only limited support for BLOB columns. You cannot currently retrieve a BLOB as an IO stream. When selecting a BLOB, the entire element is converted into a String. BLOB handling is supported by writing an empty BLOB to the database on insert/update and then executing a second query to save the BLOB.
Column Name Case Semantics
Firebird and ActiveRecord have somewhat conflicting case semantics for column names.
- Firebird
-
The standard practice is to use unquoted column names, which can be thought of as case-insensitive. (In fact, Firebird converts them to uppercase.) Quoted column names (not typically used) are case-sensitive.
- ActiveRecord
-
Attribute accessors corresponding to column names are case-sensitive. The defaults for primary key and inheritance columns are lowercase, and in general, people use lowercase attribute names.
In order to map between the differing semantics in a way that conforms to common usage for both Firebird and ActiveRecord, uppercase column names in Firebird are converted to lowercase attribute names in ActiveRecord, and vice-versa. Mixed-case column names retain their case in both directions. Lowercase (quoted) Firebird column names are not supported. This is similar to the solutions adopted by other adapters.
In general, the best approach is to use unqouted (case-insensitive) column names in your Firebird DDL (or if you must quote, use uppercase column names). These will correspond to lowercase attributes in ActiveRecord.
For example, a Firebird table based on the following DDL:
CREATE TABLE products (
id BIGINT NOT NULL PRIMARY KEY,
"TYPE" VARCHAR(50),
name VARCHAR(255) );
…will correspond to an ActiveRecord model class called Product with the following attributes: id, type, name.
Quoting "TYPE" and other Firebird reserved words:
In ActiveRecord, the default inheritance column name is type. The word type is a Firebird reserved word, so it must be quoted in any Firebird SQL statements. Because of the case mapping described above, you should always reference this column using quoted-uppercase syntax ("TYPE") within Firebird DDL or other SQL statements (as in the example above). This holds true for any other Firebird reserved words used as column names as well.
Migrations
The Firebird Adapter now supports Migrations.
Create/Drop Table and Sequence Generators
Creating or dropping a table will automatically create/drop a correpsonding sequence generator, using the default naming convension. You can specify a different name using the :sequence option; no generator is created if :sequence is set to false.
Rename Table
The Firebird #rename_table Migration should be used with caution. Firebird 1.5 lacks built-in support for this feature, so it is implemented by making a copy of the original table (including column definitions, indexes and data records), and then dropping the original table. Constraints and Triggers are not properly copied, so avoid this method if your original table includes constraints (other than the primary key) or triggers. (Consider manually copying your table or using a view instead.)
Connection Options
The following options are supported by the Rubyfb adapter. None of the options have default values.
:database-
Required option. Specifies one of: (i) a Firebird database alias; (ii) the full path of a database file; or (iii) a full Firebird connection string. Do not specify
:host,:serviceor:portas separate options when using a full connection string. :host-
Set to
"remote.host.name"for remote database connections. May be omitted for local connections if a full database path is specified for:database. Some platforms require a value of"localhost"for local connections when using a Firebird database alias. :service-
Specifies a service name for the connection. Only used if
:hostis provided. Required when connecting to a non-standard service. :port-
Specifies the connection port. Only used if
:hostis provided and:serviceis not. Required when connecting to a non-standard port and:serviceis not defined. :username-
Specifies the database user. May be omitted or set to
nil(together with:password) to use the underlying operating system user credentials on supported platforms. :password-
Specifies the database password. Must be provided if
:usernameis explicitly specified; should be omitted if OS user credentials are are being used. :charset-
Specifies the character set to be used by the connection. Refer to Firebird documentation for valid options.
:sql_role_name-
Specifies the SQL role name used by the connection.
Direct Known Subclasses
Constant Summary collapse
- TEMP_COLUMN_NAME =
'AR$TEMP_COLUMN'- ADAPTER_NAME =
'Rubyfb'.freeze
- IDENTIFIER_MAX_LENGTH =
maximum length of identifiers
30- @@boolean_domain =
{ :name => "d_boolean", :type => "smallint", :true => 1, :false => 0, :domain_pattern=>/boolean/i, :name_pattern=>/^is_/i }
Instance Method Summary collapse
-
#active? ⇒ Boolean
CONNECTION MANAGEMENT ====================================.
-
#adapter_name ⇒ Object
:nodoc:.
-
#add_column(table_name, column_name, type, options = {}) ⇒ Object
:nodoc:.
-
#add_limit_offset!(sql, options) ⇒ Object
:nodoc:.
-
#begin_db_transaction ⇒ Object
:nodoc:.
-
#change_column(table_name, column_name, type, options = {}) ⇒ Object
:nodoc:.
-
#change_column_default(table_name, column_name, default) ⇒ Object
:nodoc:.
- #change_column_null(table_name, column_name, null, default = nil) ⇒ Object
- #clear_cache! ⇒ Object
-
#column_name_length ⇒ Object
the maximum length of a column name.
-
#columns(table_name, name = nil) ⇒ Object
:nodoc:.
-
#commit_db_transaction ⇒ Object
:nodoc:.
-
#create_table(name, options = {}, &block) ⇒ Object
:nodoc:.
-
#create_table_and_sequence(name, options = {}, &block) ⇒ Object
:nodoc:.
-
#current_database ⇒ Object
SCHEMA STATEMENTS ========================================.
-
#default_sequence_name(table_name, primary_key = nil) ⇒ Object
:nodoc:.
-
#disconnect! ⇒ Object
:nodoc:.
-
#drop_table(name, options = {}) ⇒ Object
:nodoc:.
-
#dump_schema_information ⇒ Object
:nodoc:.
- #exec_insert(sql, name, binds) ⇒ Object (also: #exec_update)
- #exec_query(sql, name = 'SQL', binds = [], &block) ⇒ Object
-
#execute(sql, name = nil, &block) ⇒ Object
:nodoc:.
- #execute_procedure(procedure_name, values = {}) ⇒ Object
- #in_clause_length ⇒ Object (also: #ids_in_list_limit)
-
#index_name(table_name, options) ⇒ Object
returned shortened index name if default is too large (from oracle-enhanced).
-
#index_name_length ⇒ Object
the maximum length of an index name.
-
#indexes(table_name, name = nil) ⇒ Object
:nodoc:.
-
#initialize(connection, logger, connection_params = nil) ⇒ RubyfbAdapter
constructor
A new instance of RubyfbAdapter.
-
#insert_fixture(fixture, table_name) ⇒ Object
Inserts the given fixture into the table.
- #last_inserted_id(result) ⇒ Object
-
#native_database_types ⇒ Object
:nodoc:.
-
#next_sequence_value(sequence_name) ⇒ Object
Returns the next sequence value from a sequence generator.
-
#prefetch_primary_key?(table_name = nil) ⇒ Boolean
Returns true for Firebird adapter (since Firebird requires primary key values to be pre-fetched before insert).
- #primary_key(table_name) ⇒ Object
-
#quote(value, column = nil) ⇒ Object
We use quoting in order to implement BLOB handling.
-
#quote_column_name(column_name) ⇒ Object
:nodoc:.
-
#quote_string(string) ⇒ Object
:nodoc:.
-
#quoted_false ⇒ Object
:nodoc:.
-
#quoted_true ⇒ Object
:nodoc:.
-
#reconnect! ⇒ Object
:nodoc:.
-
#recreate_database! ⇒ Object
:nodoc:.
-
#remove_index(table_name, options) ⇒ Object
:nodoc:.
-
#rename_column(table_name, column_name, new_column_name) ⇒ Object
:nodoc:.
-
#rename_table(name, new_name) ⇒ Object
:nodoc:.
- #reset! ⇒ Object
-
#rollback_db_transaction ⇒ Object
:nodoc:.
-
#select_rows(sql, name = nil) ⇒ Object
DATABASE STATEMENTS ======================================.
- #super_create_table ⇒ Object
- #supports_ddl_transactions? ⇒ Boolean
-
#supports_migrations? ⇒ Boolean
:nodoc:.
- #supports_statement_cache? ⇒ Boolean
-
#table_alias_length ⇒ Object
:nodoc:.
- #table_exists?(table_name) ⇒ Boolean
-
#table_name_length ⇒ Object
the maximum length of a table name.
-
#tables(name = nil) ⇒ Object
:nodoc:.
- #type_cast(value, column) ⇒ Object
-
#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object
:nodoc:.
-
#write_blobs(table_name, klass, attributes, enable_coders) ⇒ Object
Writes BLOB values from attributes, as indicated by the BLOB columns of klass.
Constructor Details
#initialize(connection, logger, connection_params = nil) ⇒ RubyfbAdapter
Returns a new instance of RubyfbAdapter.
325 326 327 328 329 330 331 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 325 def initialize(connection, logger, connection_params = nil) super(connection, logger) @connection_params = connection_params @transaction = nil @blobs_disabled = 0 @statements = {} end |
Instance Method Details
#active? ⇒ Boolean
CONNECTION MANAGEMENT ====================================
455 456 457 458 459 460 461 462 463 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 455 def active? # :nodoc: return false if @connection.closed? begin execute('select first 1 cast(1 as smallint) from rdb$database') true rescue false end end |
#adapter_name ⇒ Object
:nodoc:
335 336 337 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 335 def adapter_name #:nodoc: ADAPTER_NAME end |
#add_column(table_name, column_name, type, options = {}) ⇒ Object
:nodoc:
739 740 741 742 743 744 745 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 739 def add_column(table_name, column_name, type, = {}) # :nodoc: super rescue StatementInvalid raise unless non_existent_domain_error? create_boolean_domain super end |
#add_limit_offset!(sql, options) ⇒ Object
:nodoc:
551 552 553 554 555 556 557 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 551 def add_limit_offset!(sql, ) # :nodoc: if [:limit] limit_string = "FIRST #{options[:limit]}" limit_string << " SKIP #{options[:offset]}" if [:offset] sql.sub!(/\A(\s*SELECT\s)/i, '\&' + limit_string + ' ') end end |
#begin_db_transaction ⇒ Object
:nodoc:
535 536 537 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 535 def begin_db_transaction() # :nodoc: @transaction = @connection.start_transaction end |
#change_column(table_name, column_name, type, options = {}) ⇒ Object
:nodoc:
747 748 749 750 751 752 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 747 def change_column(table_name, column_name, type, = {}) # :nodoc: change_column_type(table_name, column_name, type, ) change_column_position(table_name, column_name, [:position]) if .include?(:position) change_column_default(table_name, column_name, [:default]) if () change_column_null(table_name, column_name, [:null], [:default]) if .key?(:null) end |
#change_column_default(table_name, column_name, default) ⇒ Object
:nodoc:
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 754 def change_column_default(table_name, column_name, default) # :nodoc: table_name = table_name.to_s.upcase sql = " UPDATE rdb$relation_fields f1\n SET f1.rdb$default_source =\n (SELECT f2.rdb$default_source FROM rdb$relation_fields f2\n WHERE f2.rdb$relation_name = '\#{table_name}'\n AND f2.rdb$field_name = '\#{TEMP_COLUMN_NAME}'),\n f1.rdb$default_value =\n (SELECT f2.rdb$default_value FROM rdb$relation_fields f2\n WHERE f2.rdb$relation_name = '\#{table_name}'\n AND f2.rdb$field_name = '\#{TEMP_COLUMN_NAME}')\n WHERE f1.rdb$relation_name = '\#{table_name}'\n AND f1.rdb$field_name = '\#{ar_to_fb_case(column_name.to_s)}'\n end_sql\n transaction do\n add_column(table_name, TEMP_COLUMN_NAME, :string, :default => default)\n exec_query(sql)\n remove_column(table_name, TEMP_COLUMN_NAME)\n end\nend\n" |
#change_column_null(table_name, column_name, null, default = nil) ⇒ Object
776 777 778 779 780 781 782 783 784 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 776 def change_column_null(table_name, column_name, null, default = nil) table_name = table_name.to_s.upcase column_name = column_name.to_s.upcase unless null || default.nil? exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") end exec_query("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = #{null ? 'null' : '1'} WHERE (RDB$FIELD_NAME = '#{column_name}') and (RDB$RELATION_NAME = '#{table_name}')") end |
#clear_cache! ⇒ Object
494 495 496 497 498 499 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 494 def clear_cache! @statements.each_value do |s| s.close end @statements.clear end |
#column_name_length ⇒ Object
the maximum length of a column name
364 365 366 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 364 def column_name_length IDENTIFIER_MAX_LENGTH end |
#columns(table_name, name = nil) ⇒ Object
:nodoc:
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 652 def columns(table_name, name = nil) # :nodoc: sql = " SELECT r.rdb$field_name, r.rdb$field_source, f.rdb$field_type, f.rdb$field_sub_type,\n COALESCE(f.rdb$character_length, f.rdb$field_length) as rdb$field_length, f.rdb$field_precision, f.rdb$field_scale,\n COALESCE(r.rdb$default_source, f.rdb$default_source) as rdb$default_source,\n COALESCE(r.rdb$null_flag, f.rdb$null_flag) as rdb$null_flag\n FROM rdb$relation_fields r\n JOIN rdb$fields f ON r.rdb$field_source = f.rdb$field_name\n WHERE r.rdb$relation_name = '\#{table_name.to_s.upcase}'\n ORDER BY r.rdb$field_position\n end_sql\n\n select_rows(sql, name).collect do |row|\n field_values = row.collect do |value|\n case value\n when String then value.rstrip\n else value\n end\n end\n FirebirdColumn.new(self, *field_values)\n end\nend\n" |
#commit_db_transaction ⇒ Object
:nodoc:
539 540 541 542 543 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 539 def commit_db_transaction() # :nodoc: @transaction.commit ensure @transaction = nil end |
#create_table(name, options = {}, &block) ⇒ Object
:nodoc:
698 699 700 701 702 703 704 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 698 def create_table(name, = {}, &block) # :nodoc: create_table_and_sequence(name, , &block) rescue StatementInvalid raise unless non_existent_domain_error? create_boolean_domain create_table_and_sequence(name, , &block) end |
#create_table_and_sequence(name, options = {}, &block) ⇒ Object
:nodoc:
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 676 def create_table_and_sequence(name, = {}, &block) # :nodoc: create_sequence = [:id] != false table_td = nil super_create_table(name, ) do |td| unless create_sequence class << td attr_accessor :create_sequence def primary_key(*args) self.create_sequence = true super(*args) end end table_td = td end yield td if block_given? end if create_sequence || table_td.create_sequence sequence_name = [:sequence] || default_sequence_name(name) create_sequence(name, sequence_name) end end |
#current_database ⇒ Object
SCHEMA STATEMENTS ========================================
613 614 615 616 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 613 def current_database # :nodoc: file = @connection.database.file.split(':').last File.basename(file, '.*') end |
#default_sequence_name(table_name, primary_key = nil) ⇒ Object
:nodoc:
402 403 404 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 402 def default_sequence_name(table_name, primary_key = nil) # :nodoc: "#{table_name}_seq".upcase end |
#disconnect! ⇒ Object
:nodoc:
465 466 467 468 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 465 def disconnect! # :nodoc: clear_cache! @connection.close rescue nil end |
#drop_table(name, options = {}) ⇒ Object
:nodoc:
706 707 708 709 710 711 712 713 714 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 706 def drop_table(name, = {}) # :nodoc: super(name) unless [:sequence] == false sequence_name = [:sequence] || default_sequence_name(name) if sequence_exists?(sequence_name) drop_sequence(sequence_name) end end end |
#dump_schema_information ⇒ Object
:nodoc:
816 817 818 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 816 def dump_schema_information # :nodoc: super << ";\n" end |
#exec_insert(sql, name, binds) ⇒ Object Also known as: exec_update
524 525 526 527 528 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 524 def exec_insert(sql, name, binds) with_blobs_disabled do super end end |
#exec_query(sql, name = 'SQL', binds = [], &block) ⇒ Object
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 501 def exec_query(sql, name = 'SQL', binds = [], &block) log(sql, name, binds) do unless binds.empty? cache = @statements[sql] binds = binds.map do |col, val| type_cast(val, col) end end s = cache || @connection.create_statement(sql) s.prepare(@transaction) unless s.prepared? if Rubyfb::Statement::DDL_STATEMENT == s.type clear_cache! elsif cache.nil? && !binds.empty? @statements[sql] = cache = s end if cache s.exec(binds, @transaction, &block) else s.exec_and_close(binds, @transaction, &block) end end end |
#execute(sql, name = nil, &block) ⇒ Object
:nodoc:
485 486 487 488 489 490 491 492 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 485 def execute(sql, name = nil, &block) # :nodoc: exec_result = exec_query(sql, name, [], &block) if exec_result.instance_of?(Rubyfb::ResultSet) exec_result.close exec_result = nil end return exec_result end |
#execute_procedure(procedure_name, values = {}) ⇒ Object
829 830 831 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 829 def execute_procedure(procedure_name, values={}) @connection.prepare_call(procedure_name).execute(values, @transaction) end |
#in_clause_length ⇒ Object Also known as: ids_in_list_limit
373 374 375 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 373 def in_clause_length 1000 end |
#index_name(table_name, options) ⇒ Object
returned shortened index name if default is too large (from oracle-enhanced)
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 717 def index_name(table_name, ) #:nodoc: default_name = super(table_name, ).to_s # sometimes options can be String or Array with column names = {} unless .is_a?(Hash) identifier_max_length = [:identifier_max_length] || index_name_length return default_name if default_name.length <= identifier_max_length # remove 'index', 'on' and 'and' keywords shortened_name = "i_#{table_name}_#{Array(options[:column]) * '_'}" # leave just first three letters from each word if shortened_name.length > identifier_max_length shortened_name = shortened_name.split('_').map{|w| w[0,3]}.join('_') end # generate unique name using hash function if shortened_name.length > identifier_max_length shortened_name = 'i'+Digest::SHA1.hexdigest(default_name)[0,identifier_max_length-1] end @logger.warn "#{adapter_name} shortened default index name #{default_name} to #{shortened_name}" if @logger shortened_name end |
#index_name_length ⇒ Object
the maximum length of an index name
369 370 371 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 369 def index_name_length IDENTIFIER_MAX_LENGTH end |
#indexes(table_name, name = nil) ⇒ Object
:nodoc:
642 643 644 645 646 647 648 649 650 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 642 def indexes(table_name, name = nil) # :nodoc: (table_name, false, name).inject([]) do |indexes, row| if indexes.empty? or indexes.last.name != row[0] indexes << IndexDefinition.new(table_name, row[0].rstrip.downcase, row[1] == 1, []) end indexes.last.columns << row[2].rstrip.downcase indexes end end |
#insert_fixture(fixture, table_name) ⇒ Object
Inserts the given fixture into the table. Overridden to properly handle blobs.
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 567 def insert_fixture(fixture, table_name) #:nodoc: if ActiveRecord::Base.pluralize_table_names klass = table_name.singularize.camelize else klass = table_name.camelize end klass = klass.constantize rescue nil if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base) with_blobs_disabled do super end write_blobs(table_name, klass, fixture, false) else super end end |
#last_inserted_id(result) ⇒ Object
531 532 533 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 531 def last_inserted_id(result) nil #TODO end |
#native_database_types ⇒ Object
:nodoc:
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 378 def native_database_types # :nodoc: { :primary_key => "BIGINT NOT NULL PRIMARY KEY", :string => { :name => "varchar", :limit => 255 }, :text => { :name => "blob sub_type text" }, :integer => { :name => "bigint" }, :decimal => { :name => "decimal" }, :numeric => { :name => "numeric" }, :float => { :name => "float" }, :datetime => { :name => "timestamp" }, :timestamp => { :name => "timestamp" }, :time => { :name => "time" }, :date => { :name => "date" }, :binary => { :name => "blob sub_type 0" }, :boolean => boolean_domain } end |
#next_sequence_value(sequence_name) ⇒ Object
Returns the next sequence value from a sequence generator. Not generally called directly; used by ActiveRecord to get the next primary key value when inserting a new database record (see #prefetch_primary_key?).
562 563 564 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 562 def next_sequence_value(sequence_name) Rubyfb::Generator.new(quote_generator_name(sequence_name), @connection).next(1, @transaction) end |
#prefetch_primary_key?(table_name = nil) ⇒ Boolean
Returns true for Firebird adapter (since Firebird requires primary key values to be pre-fetched before insert). See also #next_sequence_value.
398 399 400 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 398 def prefetch_primary_key?(table_name = nil) true end |
#primary_key(table_name) ⇒ Object
636 637 638 639 640 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 636 def primary_key(table_name) if pk_row = (table_name, true).to_a.first pk_row[2].rstrip.downcase end end |
#quote(value, column = nil) ⇒ Object
We use quoting in order to implement BLOB handling. In order to do this we quote a BLOB to an empty string which will force Firebird to create an empty BLOB in the db for us.
412 413 414 415 416 417 418 419 420 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 412 def quote(value, column = nil) # :nodoc: if [Date, Time].include?(value.class) "CAST('#{type_cast(value, column).to_s(:db)}' AS #{value.acts_like?(:time) ? 'TIMESTAMP' : 'DATE'})" elsif @blobs_disabled.nonzero? && value && column && [:text, :binary].include?(column.type) "''" else super end end |
#quote_column_name(column_name) ⇒ Object
:nodoc:
426 427 428 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 426 def quote_column_name(column_name) # :nodoc: %Q("#{ar_to_fb_case(column_name.to_s)}") end |
#quote_string(string) ⇒ Object
:nodoc:
422 423 424 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 422 def quote_string(string) # :nodoc: string.gsub(/'/, "''") end |
#quoted_false ⇒ Object
:nodoc:
434 435 436 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 434 def quoted_false # :nodoc: quote(boolean_domain[:false]) end |
#quoted_true ⇒ Object
:nodoc:
430 431 432 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 430 def quoted_true # :nodoc: quote(boolean_domain[:true]) end |
#reconnect! ⇒ Object
:nodoc:
475 476 477 478 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 475 def reconnect! # :nodoc: disconnect! @connection = @connection.database.connect(*@connection_params) end |
#recreate_database! ⇒ Object
:nodoc:
618 619 620 621 622 623 624 625 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 618 def recreate_database! # :nodoc: sql = "SELECT rdb$character_set_name FROM rdb$database" charset = select_rows(sql).first[0].rstrip disconnect! @connection.database.drop(*@connection_params) Rubyfb::Database.create(@connection.database.file, @connection_params[0], @connection_params[1], 4096, charset) end |
#remove_index(table_name, options) ⇒ Object
:nodoc:
790 791 792 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 790 def remove_index(table_name, ) #:nodoc: exec_query("DROP INDEX #{quote_column_name(index_name(table_name, options))}") end |
#rename_column(table_name, column_name, new_column_name) ⇒ Object
:nodoc:
786 787 788 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 786 def rename_column(table_name, column_name, new_column_name) # :nodoc: exec_query("ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}") end |
#rename_table(name, new_name) ⇒ Object
:nodoc:
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 794 def rename_table(name, new_name) # :nodoc: if table_has_constraints_or_dependencies?(name) raise ActiveRecordError, "Table #{name} includes constraints or dependencies that are not supported by " << "the Firebird rename_table migration. Try explicitly removing the constraints/" << "dependencies first, or manually renaming the table." end transaction do copy_table(name, new_name) copy_table_indexes(name, new_name) end begin copy_table_data(name, new_name) copy_sequence_value(name, new_name) rescue drop_table(new_name) raise end drop_table(name) end |
#reset! ⇒ Object
470 471 472 473 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 470 def reset! clear_cache! super end |
#rollback_db_transaction ⇒ Object
:nodoc:
545 546 547 548 549 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 545 def rollback_db_transaction() # :nodoc: @transaction.rollback ensure @transaction = nil end |
#select_rows(sql, name = nil) ⇒ Object
DATABASE STATEMENTS ======================================
481 482 483 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 481 def select_rows(sql, name = nil) select_raw(sql, name).last end |
#super_create_table ⇒ Object
675 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 675 alias_method :super_create_table, :create_table |
#supports_ddl_transactions? ⇒ Boolean
347 348 349 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 347 def supports_ddl_transactions? true end |
#supports_migrations? ⇒ Boolean
:nodoc:
339 340 341 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 339 def supports_migrations? #:nodoc: true end |
#supports_statement_cache? ⇒ Boolean
343 344 345 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 343 def supports_statement_cache? true end |
#table_alias_length ⇒ Object
:nodoc:
354 355 356 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 354 def table_alias_length #:nodoc: IDENTIFIER_MAX_LENGTH end |
#table_exists?(table_name) ⇒ Boolean
632 633 634 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 632 def table_exists?(table_name) super(table_name.to_s.downcase) end |
#table_name_length ⇒ Object
the maximum length of a table name
359 360 361 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 359 def table_name_length IDENTIFIER_MAX_LENGTH end |
#tables(name = nil) ⇒ Object
:nodoc:
627 628 629 630 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 627 def tables(name = nil) # :nodoc: sql = "SELECT rdb$relation_name FROM rdb$relations WHERE rdb$system_flag = 0" select_rows(sql, name).collect { |row| row[0].rstrip.downcase } end |
#type_cast(value, column) ⇒ Object
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 438 def type_cast(value, column) case value when true, false value ? boolean_domain[:true] : boolean_domain[:false] when Date, Time if value.acts_like?(:time) zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal value = value.send(zone_conversion_method) if value.respond_to?(zone_conversion_method) else value end else super end end |
#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object
:nodoc:
820 821 822 823 824 825 826 827 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 820 def type_to_sql(type, limit = nil, precision = nil, scale = nil) # :nodoc: case type when :integer then integer_sql_type(limit) when :float then float_sql_type(limit) when :string then super(type, limit, precision, scale) else super(type, limit, precision, scale) end end |
#write_blobs(table_name, klass, attributes, enable_coders) ⇒ Object
Writes BLOB values from attributes, as indicated by the BLOB columns of klass.
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 |
# File 'lib/active_record/connection_adapters/rubyfb_adapter.rb', line 585 def write_blobs(table_name, klass, attributes, enable_coders) #:nodoc: # is class with composite primary key> is_with_cpk = klass.respond_to?(:composite?) && klass.composite? if is_with_cpk id = klass.primary_key.map {|pk| attributes[pk.to_s] } else id = quote(attributes[klass.primary_key]) end klass.columns.select { |col| col.sql_type =~ /BLOB$/i }.each do |col| value = attributes[col.name] next if value.nil? || (value == '') klass.serialized_attributes[col.name].tap do |coder| if enable_coders && coder value = dump_blob_value(col, coder, value) elsif value.respond_to?(:read) value = value.read end end uncached do sql = is_with_cpk ? "UPDATE #{quote_table_name(table_name)} set #{quote_column_name(col.name)} = ? WHERE #{klass.composite_where_clause(id)}" : "UPDATE #{quote_table_name(table_name)} set #{quote_column_name(col.name)} = ? WHERE #{quote_column_name(klass.primary_key)} = #{id}" @connection.execute_for(sql, [value.to_s], @transaction) end end end |