activerecord-rdb-adapter 0.9.4 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -8
- data/extconf.rb +93 -93
- data/fb.c +3072 -3072
- data/fb_extensions.rb +21 -21
- data/lib/active_model/type/integer.rb +67 -67
- data/lib/active_record/connection_adapters/rdb/database_limits.rb +35 -35
- data/lib/active_record/connection_adapters/rdb/database_statements.rb +186 -183
- data/lib/active_record/connection_adapters/rdb/quoting.rb +152 -152
- data/lib/active_record/connection_adapters/rdb/schema_creation.rb +52 -52
- data/lib/active_record/connection_adapters/rdb/schema_dumper.rb +23 -23
- data/lib/active_record/connection_adapters/rdb/schema_statements.rb +431 -431
- data/lib/active_record/connection_adapters/rdb/table_definition.rb +28 -28
- data/lib/active_record/connection_adapters/rdb_adapter.rb +163 -163
- data/lib/active_record/connection_adapters/rdb_column.rb +69 -69
- data/lib/active_record/rdb_base.rb +34 -34
- data/lib/active_record/tasks/rdb_database_tasks.rb +78 -78
- data/lib/activerecord-rdb-adapter.rb +10 -10
- data/lib/arel/visitors/rdb_visitor.rb +135 -135
- metadata +3 -4
@@ -1,28 +1,28 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module ConnectionAdapters
|
3
|
-
module Rdb
|
4
|
-
module ColumnMethods # :nodoc:
|
5
|
-
|
6
|
-
attr_accessor :needs_sequence
|
7
|
-
|
8
|
-
def primary_key(name, type = :primary_key, **options)
|
9
|
-
self.needs_sequence = true
|
10
|
-
super
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition # :nodoc:
|
16
|
-
include ColumnMethods
|
17
|
-
|
18
|
-
def new_column_definition(name, type, **options)
|
19
|
-
super
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class Table < ActiveRecord::ConnectionAdapters::Table # :nodoc:
|
24
|
-
include ColumnMethods
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module Rdb
|
4
|
+
module ColumnMethods # :nodoc:
|
5
|
+
|
6
|
+
attr_accessor :needs_sequence
|
7
|
+
|
8
|
+
def primary_key(name, type = :primary_key, **options)
|
9
|
+
self.needs_sequence = true
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition # :nodoc:
|
16
|
+
include ColumnMethods
|
17
|
+
|
18
|
+
def new_column_definition(name, type, **options)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Table < ActiveRecord::ConnectionAdapters::Table # :nodoc:
|
24
|
+
include ColumnMethods
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,163 +1,163 @@
|
|
1
|
-
require 'fb'
|
2
|
-
require 'base64'
|
3
|
-
require 'arel'
|
4
|
-
require 'arel/visitors/rdb_visitor'
|
5
|
-
|
6
|
-
require 'active_record'
|
7
|
-
require 'active_record/base'
|
8
|
-
require 'active_record/connection_adapters/abstract_adapter'
|
9
|
-
require 'active_record/connection_adapters/rdb/database_statements'
|
10
|
-
require 'active_record/connection_adapters/rdb/database_limits'
|
11
|
-
require 'active_record/connection_adapters/rdb/schema_creation'
|
12
|
-
require 'active_record/connection_adapters/rdb/schema_dumper'
|
13
|
-
require 'active_record/connection_adapters/rdb/schema_statements'
|
14
|
-
require 'active_record/connection_adapters/rdb/quoting'
|
15
|
-
require 'active_record/connection_adapters/rdb/table_definition'
|
16
|
-
require 'active_record/connection_adapters/rdb_column'
|
17
|
-
require 'active_record/rdb_base'
|
18
|
-
|
19
|
-
module ActiveRecord
|
20
|
-
module ConnectionAdapters
|
21
|
-
class RdbAdapter < AbstractAdapter # :nodoc:
|
22
|
-
include Rdb::DatabaseLimits
|
23
|
-
include Rdb::DatabaseStatements
|
24
|
-
include Rdb::Quoting
|
25
|
-
include Rdb::SchemaStatements
|
26
|
-
|
27
|
-
@@default_transaction_isolation = :read_committed
|
28
|
-
cattr_accessor :default_transaction_isolation
|
29
|
-
|
30
|
-
ADAPTER_NAME = 'rdb'.freeze
|
31
|
-
|
32
|
-
def initialize(connection, logger = nil, config = {})
|
33
|
-
super(connection, logger, config)
|
34
|
-
# Our Responsibility
|
35
|
-
@config = config
|
36
|
-
@visitor = Arel::Visitors::Rdb.new self
|
37
|
-
@prepared_statements = true
|
38
|
-
@visitor.extend(DetermineIfPreparableVisitor)
|
39
|
-
end
|
40
|
-
|
41
|
-
def arel_visitor
|
42
|
-
Arel::Visitors::Rdb.new self
|
43
|
-
end
|
44
|
-
|
45
|
-
def valid_type?(type)
|
46
|
-
!native_database_types[type].nil? || !native_database_types[type.type].nil?
|
47
|
-
end
|
48
|
-
|
49
|
-
def adapter_name
|
50
|
-
ADAPTER_NAME
|
51
|
-
end
|
52
|
-
|
53
|
-
def schema_creation
|
54
|
-
Rdb::SchemaCreation.new self
|
55
|
-
end
|
56
|
-
|
57
|
-
def supports_migrations?
|
58
|
-
true
|
59
|
-
end
|
60
|
-
|
61
|
-
def supports_primary_key?
|
62
|
-
true
|
63
|
-
end
|
64
|
-
|
65
|
-
def supports_count_distinct?
|
66
|
-
true
|
67
|
-
end
|
68
|
-
|
69
|
-
def supports_ddl_transactions?
|
70
|
-
true
|
71
|
-
end
|
72
|
-
|
73
|
-
def supports_transaction_isolation?
|
74
|
-
true
|
75
|
-
end
|
76
|
-
|
77
|
-
def supports_savepoints?
|
78
|
-
true
|
79
|
-
end
|
80
|
-
|
81
|
-
def prefetch_primary_key?(_table_name = nil)
|
82
|
-
true
|
83
|
-
end
|
84
|
-
|
85
|
-
def ids_in_list_limit
|
86
|
-
1499
|
87
|
-
end
|
88
|
-
|
89
|
-
def supports_multi_insert?
|
90
|
-
false
|
91
|
-
end
|
92
|
-
|
93
|
-
def active?
|
94
|
-
return false unless @connection.open?
|
95
|
-
# return true if @connection.transaction_started
|
96
|
-
@connection.query('SELECT 1 FROM RDB$DATABASE')
|
97
|
-
true
|
98
|
-
rescue StandardError
|
99
|
-
false
|
100
|
-
end
|
101
|
-
|
102
|
-
def reconnect!
|
103
|
-
disconnect!
|
104
|
-
@connection = ::Fb::Database.connect(@config)
|
105
|
-
end
|
106
|
-
|
107
|
-
def disconnect!
|
108
|
-
super
|
109
|
-
begin
|
110
|
-
@connection.close
|
111
|
-
rescue StandardError
|
112
|
-
nil
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def reset!
|
117
|
-
reconnect!
|
118
|
-
end
|
119
|
-
|
120
|
-
def requires_reloading?
|
121
|
-
false
|
122
|
-
end
|
123
|
-
|
124
|
-
def create_savepoint(name = current_savepoint_name)
|
125
|
-
execute("SAVEPOINT #{name}")
|
126
|
-
end
|
127
|
-
|
128
|
-
def rollback_to_savepoint(name = current_savepoint_name)
|
129
|
-
execute("ROLLBACK TO SAVEPOINT #{name}")
|
130
|
-
end
|
131
|
-
|
132
|
-
def release_savepoint(name = current_savepoint_name)
|
133
|
-
execute("RELEASE SAVEPOINT #{name}")
|
134
|
-
end
|
135
|
-
|
136
|
-
protected
|
137
|
-
|
138
|
-
def initialize_type_map(map)
|
139
|
-
super
|
140
|
-
map.register_type(/timestamp/i, Type::DateTime.new)
|
141
|
-
map.alias_type(/blob sub_type text/i, 'text')
|
142
|
-
end
|
143
|
-
|
144
|
-
def translate_exception(e, message)
|
145
|
-
case e.message
|
146
|
-
when /violation of FOREIGN KEY constraint/
|
147
|
-
ActiveRecord::InvalidForeignKey.new(message)
|
148
|
-
when /violation of PRIMARY or UNIQUE KEY constraint/, /attempt to store duplicate value/
|
149
|
-
ActiveRecord::RecordNotUnique.new(message)
|
150
|
-
when /This operation is not defined for system tables/
|
151
|
-
ActiveRecord::ActiveRecordError.new(message)
|
152
|
-
when /Column does not belong to referenced table/,
|
153
|
-
/Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements/,
|
154
|
-
/The cursor identified in the UPDATE or DELETE statement is not positioned on a row/,
|
155
|
-
/Overflow occurred during data type conversion/
|
156
|
-
ActiveRecord::StatementInvalid.new(message)
|
157
|
-
else
|
158
|
-
super
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
1
|
+
require 'fb'
|
2
|
+
require 'base64'
|
3
|
+
require 'arel'
|
4
|
+
require 'arel/visitors/rdb_visitor'
|
5
|
+
|
6
|
+
require 'active_record'
|
7
|
+
require 'active_record/base'
|
8
|
+
require 'active_record/connection_adapters/abstract_adapter'
|
9
|
+
require 'active_record/connection_adapters/rdb/database_statements'
|
10
|
+
require 'active_record/connection_adapters/rdb/database_limits'
|
11
|
+
require 'active_record/connection_adapters/rdb/schema_creation'
|
12
|
+
require 'active_record/connection_adapters/rdb/schema_dumper'
|
13
|
+
require 'active_record/connection_adapters/rdb/schema_statements'
|
14
|
+
require 'active_record/connection_adapters/rdb/quoting'
|
15
|
+
require 'active_record/connection_adapters/rdb/table_definition'
|
16
|
+
require 'active_record/connection_adapters/rdb_column'
|
17
|
+
require 'active_record/rdb_base'
|
18
|
+
|
19
|
+
module ActiveRecord
|
20
|
+
module ConnectionAdapters
|
21
|
+
class RdbAdapter < AbstractAdapter # :nodoc:
|
22
|
+
include Rdb::DatabaseLimits
|
23
|
+
include Rdb::DatabaseStatements
|
24
|
+
include Rdb::Quoting
|
25
|
+
include Rdb::SchemaStatements
|
26
|
+
|
27
|
+
@@default_transaction_isolation = :read_committed
|
28
|
+
cattr_accessor :default_transaction_isolation
|
29
|
+
|
30
|
+
ADAPTER_NAME = 'rdb'.freeze
|
31
|
+
|
32
|
+
def initialize(connection, logger = nil, config = {})
|
33
|
+
super(connection, logger, config)
|
34
|
+
# Our Responsibility
|
35
|
+
@config = config
|
36
|
+
@visitor = Arel::Visitors::Rdb.new self
|
37
|
+
@prepared_statements = true
|
38
|
+
@visitor.extend(DetermineIfPreparableVisitor)
|
39
|
+
end
|
40
|
+
|
41
|
+
def arel_visitor
|
42
|
+
Arel::Visitors::Rdb.new self
|
43
|
+
end
|
44
|
+
|
45
|
+
def valid_type?(type)
|
46
|
+
!native_database_types[type].nil? || !native_database_types[type.type].nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
def adapter_name
|
50
|
+
ADAPTER_NAME
|
51
|
+
end
|
52
|
+
|
53
|
+
def schema_creation
|
54
|
+
Rdb::SchemaCreation.new self
|
55
|
+
end
|
56
|
+
|
57
|
+
def supports_migrations?
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def supports_primary_key?
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
def supports_count_distinct?
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def supports_ddl_transactions?
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
def supports_transaction_isolation?
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def supports_savepoints?
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
def prefetch_primary_key?(_table_name = nil)
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
def ids_in_list_limit
|
86
|
+
1499
|
87
|
+
end
|
88
|
+
|
89
|
+
def supports_multi_insert?
|
90
|
+
false
|
91
|
+
end
|
92
|
+
|
93
|
+
def active?
|
94
|
+
return false unless @connection.open?
|
95
|
+
# return true if @connection.transaction_started
|
96
|
+
@connection.query('SELECT 1 FROM RDB$DATABASE')
|
97
|
+
true
|
98
|
+
rescue StandardError
|
99
|
+
false
|
100
|
+
end
|
101
|
+
|
102
|
+
def reconnect!
|
103
|
+
disconnect!
|
104
|
+
@connection = ::Fb::Database.connect(@config)
|
105
|
+
end
|
106
|
+
|
107
|
+
def disconnect!
|
108
|
+
super
|
109
|
+
begin
|
110
|
+
@connection.close
|
111
|
+
rescue StandardError
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def reset!
|
117
|
+
reconnect!
|
118
|
+
end
|
119
|
+
|
120
|
+
def requires_reloading?
|
121
|
+
false
|
122
|
+
end
|
123
|
+
|
124
|
+
def create_savepoint(name = current_savepoint_name)
|
125
|
+
execute("SAVEPOINT #{name}")
|
126
|
+
end
|
127
|
+
|
128
|
+
def rollback_to_savepoint(name = current_savepoint_name)
|
129
|
+
execute("ROLLBACK TO SAVEPOINT #{name}")
|
130
|
+
end
|
131
|
+
|
132
|
+
def release_savepoint(name = current_savepoint_name)
|
133
|
+
execute("RELEASE SAVEPOINT #{name}")
|
134
|
+
end
|
135
|
+
|
136
|
+
protected
|
137
|
+
|
138
|
+
def initialize_type_map(map)
|
139
|
+
super
|
140
|
+
map.register_type(/timestamp/i, Type::DateTime.new)
|
141
|
+
map.alias_type(/blob sub_type text/i, 'text')
|
142
|
+
end
|
143
|
+
|
144
|
+
def translate_exception(e, message)
|
145
|
+
case e.message
|
146
|
+
when /violation of FOREIGN KEY constraint/
|
147
|
+
ActiveRecord::InvalidForeignKey.new(message)
|
148
|
+
when /violation of PRIMARY or UNIQUE KEY constraint/, /attempt to store duplicate value/
|
149
|
+
ActiveRecord::RecordNotUnique.new(message)
|
150
|
+
when /This operation is not defined for system tables/
|
151
|
+
ActiveRecord::ActiveRecordError.new(message)
|
152
|
+
when /Column does not belong to referenced table/,
|
153
|
+
/Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements/,
|
154
|
+
/The cursor identified in the UPDATE or DELETE statement is not positioned on a row/,
|
155
|
+
/Overflow occurred during data type conversion/
|
156
|
+
ActiveRecord::StatementInvalid.new(message)
|
157
|
+
else
|
158
|
+
super
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -1,69 +1,69 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module ConnectionAdapters
|
3
|
-
class RdbColumn < Column # :nodoc:
|
4
|
-
class << self
|
5
|
-
def sql_type_for(field)
|
6
|
-
sql_type = field[:sql_type]
|
7
|
-
sub_type = field[:sql_subtype]
|
8
|
-
|
9
|
-
sql_type << case sql_type
|
10
|
-
when /(numeric|decimal)/i
|
11
|
-
"(#{field[:precision]},#{field[:scale].abs})"
|
12
|
-
when /(int|float|double|char|varchar|bigint)/i
|
13
|
-
"(#{field[:length]})"
|
14
|
-
else
|
15
|
-
''
|
16
|
-
end
|
17
|
-
|
18
|
-
sql_type << ' sub_type text' if /blob/i.match?(sql_type) && sub_type == 1
|
19
|
-
sql_type
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
attr_reader :sub_type, :domain
|
24
|
-
|
25
|
-
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, rdb_options = {})
|
26
|
-
@domain, @sub_type = rdb_options.values_at(:domain, :sub_type)
|
27
|
-
name = name.dup
|
28
|
-
name.downcase!
|
29
|
-
super(name, parse_default(default), sql_type_metadata, null, table_name)
|
30
|
-
end
|
31
|
-
|
32
|
-
def sql_type
|
33
|
-
@sql_type_metadata[:sql_type]
|
34
|
-
end
|
35
|
-
|
36
|
-
def type
|
37
|
-
@sql_type_metadata[:type]
|
38
|
-
end
|
39
|
-
|
40
|
-
def precision
|
41
|
-
@sql_type_metadata[:precision]
|
42
|
-
end
|
43
|
-
|
44
|
-
def scale
|
45
|
-
@sql_type_metadata[:scale]
|
46
|
-
end
|
47
|
-
|
48
|
-
def limit
|
49
|
-
@sql_type_metadata[:limit]
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def parse_default(default)
|
55
|
-
return if default.nil? || /null/i.match?(default)
|
56
|
-
d = default.dup
|
57
|
-
d.gsub!(/^\s*DEFAULT\s+/i, '')
|
58
|
-
d.gsub!(/(^'|'$)/, '')
|
59
|
-
d
|
60
|
-
end
|
61
|
-
|
62
|
-
def simplified_type(field_type)
|
63
|
-
return :datetime if /timestamp/i.match?(field_type)
|
64
|
-
return :text if /blob sub_type text/i.match?(field_type)
|
65
|
-
super
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class RdbColumn < Column # :nodoc:
|
4
|
+
class << self
|
5
|
+
def sql_type_for(field)
|
6
|
+
sql_type = field[:sql_type]
|
7
|
+
sub_type = field[:sql_subtype]
|
8
|
+
|
9
|
+
sql_type << case sql_type
|
10
|
+
when /(numeric|decimal)/i
|
11
|
+
"(#{field[:precision]},#{field[:scale].abs})"
|
12
|
+
when /(int|float|double|char|varchar|bigint)/i
|
13
|
+
"(#{field[:length]})"
|
14
|
+
else
|
15
|
+
''
|
16
|
+
end
|
17
|
+
|
18
|
+
sql_type << ' sub_type text' if /blob/i.match?(sql_type) && sub_type == 1
|
19
|
+
sql_type
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :sub_type, :domain
|
24
|
+
|
25
|
+
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, rdb_options = {})
|
26
|
+
@domain, @sub_type = rdb_options.values_at(:domain, :sub_type)
|
27
|
+
name = name.dup
|
28
|
+
name.downcase!
|
29
|
+
super(name, parse_default(default), sql_type_metadata, null, table_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def sql_type
|
33
|
+
@sql_type_metadata[:sql_type]
|
34
|
+
end
|
35
|
+
|
36
|
+
def type
|
37
|
+
@sql_type_metadata[:type]
|
38
|
+
end
|
39
|
+
|
40
|
+
def precision
|
41
|
+
@sql_type_metadata[:precision]
|
42
|
+
end
|
43
|
+
|
44
|
+
def scale
|
45
|
+
@sql_type_metadata[:scale]
|
46
|
+
end
|
47
|
+
|
48
|
+
def limit
|
49
|
+
@sql_type_metadata[:limit]
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def parse_default(default)
|
55
|
+
return if default.nil? || /null/i.match?(default)
|
56
|
+
d = default.dup
|
57
|
+
d.gsub!(/^\s*DEFAULT\s+/i, '')
|
58
|
+
d.gsub!(/(^'|'$)/, '')
|
59
|
+
d
|
60
|
+
end
|
61
|
+
|
62
|
+
def simplified_type(field_type)
|
63
|
+
return :datetime if /timestamp/i.match?(field_type)
|
64
|
+
return :text if /blob sub_type text/i.match?(field_type)
|
65
|
+
super
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|