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,34 +1,34 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module ConnectionHandling # :nodoc:
|
3
|
-
def rdb_connection(config)
|
4
|
-
require 'fb'
|
5
|
-
config = rdb_connection_config(config)
|
6
|
-
db = ::Fb::Database.new(config)
|
7
|
-
@database = db
|
8
|
-
begin
|
9
|
-
connection = db.connect
|
10
|
-
rescue StandardError
|
11
|
-
unless config[:create]
|
12
|
-
require 'pp'
|
13
|
-
pp config
|
14
|
-
raise ConnectionNotEstablished, 'No Firebird connections established.'
|
15
|
-
end
|
16
|
-
connection = db.create.connect
|
17
|
-
end
|
18
|
-
ConnectionAdapters::RdbAdapter.new(connection, logger, config)
|
19
|
-
end
|
20
|
-
|
21
|
-
def rdb_connection_config(config)
|
22
|
-
config = config.symbolize_keys.dup.reverse_merge(downcase_names: true)
|
23
|
-
port = config[:port] || 3050
|
24
|
-
raise ArgumentError, 'No database specified. Missing argument: database.' unless config[:database]
|
25
|
-
config[:database] = File.expand_path(config[:database], defined?(Rails) && Rails.root) if config[:host].nil? || /localhost/i.match?(config[:host])
|
26
|
-
config[:database] = "#{config[:host]}/#{port}:#{config[:database]}" if config[:host]
|
27
|
-
# config[:charset] = config[:charset].gsub(/-/, '') if config[:charset]
|
28
|
-
# config[:encoding] = config[:encoding].gsub(/-/, '') if config[:encoding]
|
29
|
-
config[:page_size] = 8192 unless config[:page_size]
|
30
|
-
config[:readonly_selects] = true unless config[:readonly_selects].present?
|
31
|
-
config
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionHandling # :nodoc:
|
3
|
+
def rdb_connection(config)
|
4
|
+
require 'fb'
|
5
|
+
config = rdb_connection_config(config)
|
6
|
+
db = ::Fb::Database.new(config)
|
7
|
+
@database = db
|
8
|
+
begin
|
9
|
+
connection = db.connect
|
10
|
+
rescue StandardError
|
11
|
+
unless config[:create]
|
12
|
+
require 'pp'
|
13
|
+
pp config
|
14
|
+
raise ConnectionNotEstablished, 'No Firebird connections established.'
|
15
|
+
end
|
16
|
+
connection = db.create.connect
|
17
|
+
end
|
18
|
+
ConnectionAdapters::RdbAdapter.new(connection, logger, config)
|
19
|
+
end
|
20
|
+
|
21
|
+
def rdb_connection_config(config)
|
22
|
+
config = config.symbolize_keys.dup.reverse_merge(downcase_names: true)
|
23
|
+
port = config[:port] || 3050
|
24
|
+
raise ArgumentError, 'No database specified. Missing argument: database.' unless config[:database]
|
25
|
+
config[:database] = File.expand_path(config[:database], defined?(Rails) && Rails.root) if config[:host].nil? || /localhost/i.match?(config[:host])
|
26
|
+
config[:database] = "#{config[:host]}/#{port}:#{config[:database]}" if config[:host]
|
27
|
+
# config[:charset] = config[:charset].gsub(/-/, '') if config[:charset]
|
28
|
+
# config[:encoding] = config[:encoding].gsub(/-/, '') if config[:encoding]
|
29
|
+
config[:page_size] = 8192 unless config[:page_size]
|
30
|
+
config[:readonly_selects] = true unless config[:readonly_selects].present?
|
31
|
+
config
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,78 +1,78 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Tasks # :nodoc:
|
3
|
-
class RdbDatabaseTasks # :nodoc:
|
4
|
-
delegate :rdb_connection, :rdb_connection_config, :establish_connection, to: ::ActiveRecord::Base
|
5
|
-
|
6
|
-
def initialize(configuration)
|
7
|
-
@configuration = rdb_connection_config(configuration)
|
8
|
-
end
|
9
|
-
|
10
|
-
def create
|
11
|
-
rdb_database.create
|
12
|
-
# create_db
|
13
|
-
establish_connection configuration
|
14
|
-
rescue ::Fb::Error => e
|
15
|
-
raise unless e.message.include?('File exists')
|
16
|
-
raise DatabaseAlreadyExists
|
17
|
-
end
|
18
|
-
|
19
|
-
def drop
|
20
|
-
establish_connection configuration
|
21
|
-
rdb_database.drop
|
22
|
-
rescue ::Fb::Error => e
|
23
|
-
raise ::ActiveRecord::ConnectionNotEstablished, e.message
|
24
|
-
end
|
25
|
-
|
26
|
-
def purge
|
27
|
-
begin
|
28
|
-
drop
|
29
|
-
rescue StandardError
|
30
|
-
nil
|
31
|
-
end
|
32
|
-
create
|
33
|
-
end
|
34
|
-
|
35
|
-
def structure_dump(filename, structure_dump_flags = nil)
|
36
|
-
isql :extract, output: filename
|
37
|
-
end
|
38
|
-
|
39
|
-
def structure_load(filename, structure_load_flags = nil)
|
40
|
-
isql input: filename
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def rdb_database
|
46
|
-
::Fb::Database.new(configuration)
|
47
|
-
end
|
48
|
-
|
49
|
-
# Executes isql commands to load/dump the schema.
|
50
|
-
# The generated command might look like this:
|
51
|
-
# isql db/development.fdb -user SYSDBA -password masterkey -extract
|
52
|
-
def isql(*args)
|
53
|
-
opts = args.extract_options!
|
54
|
-
user, pass = configuration.values_at(:username, :password)
|
55
|
-
user ||= configuration[:user]
|
56
|
-
opts.reverse_merge!(user: user, password: pass)
|
57
|
-
cmd = [isql_executable, configuration[:database]]
|
58
|
-
cmd += opts.map { |name, val| "-#{name} #{val}" }
|
59
|
-
cmd += args.map { |flag| "-#{flag}" }
|
60
|
-
cmd = cmd.join(' ')
|
61
|
-
raise "Error running: #{cmd}" unless Kernel.system(cmd)
|
62
|
-
end
|
63
|
-
|
64
|
-
def isql_create(*_args)
|
65
|
-
"#{isql_executable} -input "
|
66
|
-
end
|
67
|
-
|
68
|
-
# Finds the isql command line utility from the PATH
|
69
|
-
# Many linux distros call this program isql-fb, instead of isql
|
70
|
-
def isql_executable
|
71
|
-
"/opt/RedDatabase/bin/isql"
|
72
|
-
end
|
73
|
-
|
74
|
-
attr_reader :configuration
|
75
|
-
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Tasks # :nodoc:
|
3
|
+
class RdbDatabaseTasks # :nodoc:
|
4
|
+
delegate :rdb_connection, :rdb_connection_config, :establish_connection, to: ::ActiveRecord::Base
|
5
|
+
|
6
|
+
def initialize(configuration)
|
7
|
+
@configuration = rdb_connection_config(configuration)
|
8
|
+
end
|
9
|
+
|
10
|
+
def create
|
11
|
+
rdb_database.create
|
12
|
+
# create_db
|
13
|
+
establish_connection configuration
|
14
|
+
rescue ::Fb::Error => e
|
15
|
+
raise unless e.message.include?('File exists')
|
16
|
+
raise DatabaseAlreadyExists
|
17
|
+
end
|
18
|
+
|
19
|
+
def drop
|
20
|
+
establish_connection configuration
|
21
|
+
rdb_database.drop
|
22
|
+
rescue ::Fb::Error => e
|
23
|
+
raise ::ActiveRecord::ConnectionNotEstablished, e.message
|
24
|
+
end
|
25
|
+
|
26
|
+
def purge
|
27
|
+
begin
|
28
|
+
drop
|
29
|
+
rescue StandardError
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
create
|
33
|
+
end
|
34
|
+
|
35
|
+
def structure_dump(filename, structure_dump_flags = nil)
|
36
|
+
isql :extract, output: filename
|
37
|
+
end
|
38
|
+
|
39
|
+
def structure_load(filename, structure_load_flags = nil)
|
40
|
+
isql input: filename
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def rdb_database
|
46
|
+
::Fb::Database.new(configuration)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Executes isql commands to load/dump the schema.
|
50
|
+
# The generated command might look like this:
|
51
|
+
# isql db/development.fdb -user SYSDBA -password masterkey -extract
|
52
|
+
def isql(*args)
|
53
|
+
opts = args.extract_options!
|
54
|
+
user, pass = configuration.values_at(:username, :password)
|
55
|
+
user ||= configuration[:user]
|
56
|
+
opts.reverse_merge!(user: user, password: pass)
|
57
|
+
cmd = [isql_executable, configuration[:database]]
|
58
|
+
cmd += opts.map { |name, val| "-#{name} #{val}" }
|
59
|
+
cmd += args.map { |flag| "-#{flag}" }
|
60
|
+
cmd = cmd.join(' ')
|
61
|
+
raise "Error running: #{cmd}" unless Kernel.system(cmd)
|
62
|
+
end
|
63
|
+
|
64
|
+
def isql_create(*_args)
|
65
|
+
"#{isql_executable} -input "
|
66
|
+
end
|
67
|
+
|
68
|
+
# Finds the isql command line utility from the PATH
|
69
|
+
# Many linux distros call this program isql-fb, instead of isql
|
70
|
+
def isql_executable
|
71
|
+
"/opt/RedDatabase/bin/isql"
|
72
|
+
end
|
73
|
+
|
74
|
+
attr_reader :configuration
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require 'active_record/connection_adapters/rdb_adapter'
|
2
|
-
|
3
|
-
if defined?(::Rails::Railtie) && ::ActiveRecord::VERSION::MAJOR > 3
|
4
|
-
class Railtie < ::Rails::Railtie # :nodoc:
|
5
|
-
rake_tasks do
|
6
|
-
load 'active_record/tasks/rdb_database_tasks.rb'
|
7
|
-
ActiveRecord::Tasks::DatabaseTasks.register_task(/rdb/, ActiveRecord::Tasks::RdbDatabaseTasks)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
1
|
+
require 'active_record/connection_adapters/rdb_adapter'
|
2
|
+
|
3
|
+
if defined?(::Rails::Railtie) && ::ActiveRecord::VERSION::MAJOR > 3
|
4
|
+
class Railtie < ::Rails::Railtie # :nodoc:
|
5
|
+
rake_tasks do
|
6
|
+
load 'active_record/tasks/rdb_database_tasks.rb'
|
7
|
+
ActiveRecord::Tasks::DatabaseTasks.register_task(/rdb/, ActiveRecord::Tasks::RdbDatabaseTasks)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -1,135 +1,135 @@
|
|
1
|
-
module Arel
|
2
|
-
module Visitors
|
3
|
-
class Rdb < Arel::Visitors::ToSql # :nodoc
|
4
|
-
private
|
5
|
-
|
6
|
-
def visit_Arel_Nodes_InsertStatement(o, collector)
|
7
|
-
collector << "INSERT INTO "
|
8
|
-
collector = visit o.relation, collector
|
9
|
-
|
10
|
-
unless o.columns.empty?
|
11
|
-
collector << " ("
|
12
|
-
o.columns.each_with_index do |x, i|
|
13
|
-
collector << ", " unless i == 0
|
14
|
-
collector << quote_column_name(x.name)
|
15
|
-
end
|
16
|
-
collector << ")"
|
17
|
-
end
|
18
|
-
|
19
|
-
if o.values
|
20
|
-
maybe_visit o.values, collector
|
21
|
-
elsif o.select
|
22
|
-
maybe_visit o.select, collector
|
23
|
-
else
|
24
|
-
collector
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def visit_Arel_Nodes_SelectStatement(o, collector)
|
29
|
-
collector << 'SELECT '
|
30
|
-
collector = visit o.offset, collector if o.offset && !o.limit
|
31
|
-
|
32
|
-
collector = o.cores.inject(collector) do |c, x|
|
33
|
-
visit_Arel_Nodes_SelectCore(x, c)
|
34
|
-
end
|
35
|
-
|
36
|
-
unless o.orders.empty?
|
37
|
-
collector << ORDER_BY
|
38
|
-
len = o.orders.length - 1
|
39
|
-
o.orders.each_with_index do |x, i|
|
40
|
-
collector = visit(x, collector)
|
41
|
-
collector << COMMA unless len == i
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
if o.limit && o.offset
|
46
|
-
collector = limit_with_rows o, collector
|
47
|
-
elsif o.limit && !o.offset
|
48
|
-
collector = visit o.limit, collector
|
49
|
-
end
|
50
|
-
|
51
|
-
maybe_visit o.lock, collector
|
52
|
-
end
|
53
|
-
|
54
|
-
def visit_Arel_Nodes_SelectCore(o, collector)
|
55
|
-
if o.set_quantifier
|
56
|
-
collector = visit o.set_quantifier, collector
|
57
|
-
collector << SPACE
|
58
|
-
end
|
59
|
-
|
60
|
-
unless o.projections.empty?
|
61
|
-
len = o.projections.length - 1
|
62
|
-
o.projections.each_with_index do |x, i|
|
63
|
-
collector = visit(x, collector)
|
64
|
-
collector << COMMA unless len == i
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
if o.source && !o.source.empty?
|
69
|
-
collector << ' FROM '
|
70
|
-
collector = visit o.source, collector
|
71
|
-
end
|
72
|
-
|
73
|
-
unless o.wheres.empty?
|
74
|
-
collector << WHERE
|
75
|
-
len = o.wheres.length - 1
|
76
|
-
o.wheres.each_with_index do |x, i|
|
77
|
-
collector = visit(x, collector)
|
78
|
-
collector << AND unless len == i
|
79
|
-
end
|
80
|
-
end
|
81
|
-
unless o.groups.empty?
|
82
|
-
collector << GROUP_BY
|
83
|
-
len = o.groups.length - 1
|
84
|
-
o.groups.each_with_index do |x, i|
|
85
|
-
collector = visit(x, collector)
|
86
|
-
collector << COMMA unless len == i
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
if Rails::VERSION::MAJOR < 5
|
91
|
-
collector = maybe_visit o.having, collector
|
92
|
-
else
|
93
|
-
unless o.havings.empty?
|
94
|
-
collector << ' HAVING '
|
95
|
-
inject_join o.havings, collector, AND
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
collector
|
100
|
-
end
|
101
|
-
|
102
|
-
def visit_Arel_Nodes_Limit(o, collector)
|
103
|
-
collector << ' ROWS '
|
104
|
-
visit o.expr, collector
|
105
|
-
end
|
106
|
-
|
107
|
-
def visit_Arel_Nodes_Offset(o, collector)
|
108
|
-
collector << ' SKIP '
|
109
|
-
visit o.expr, collector
|
110
|
-
end
|
111
|
-
|
112
|
-
def limit_with_rows o, collector
|
113
|
-
o.offset.expr.value = ActiveModel::Attribute.with_cast_value('OFFSET'.freeze,
|
114
|
-
o.offset.expr.value.value + 1,
|
115
|
-
ActiveModel::Type.default_value)
|
116
|
-
offset = o.offset.expr.value
|
117
|
-
o.limit.expr.value = ActiveModel::Attribute.with_cast_value('LIMIT'.freeze,
|
118
|
-
o.limit.expr.value.value + (offset.value - 1),
|
119
|
-
ActiveModel::Type.default_value)
|
120
|
-
limit = o.limit.expr.value
|
121
|
-
collector << ' ROWS '
|
122
|
-
collector.add_bind(offset) { |i| '?' }
|
123
|
-
collector << ' TO '
|
124
|
-
collector.add_bind(limit) { |i| '?' }
|
125
|
-
end
|
126
|
-
|
127
|
-
def quote_column_name name
|
128
|
-
return name if Arel::Nodes::SqlLiteral === name
|
129
|
-
|
130
|
-
@connection.quote_column_name(name)
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class Rdb < Arel::Visitors::ToSql # :nodoc
|
4
|
+
private
|
5
|
+
|
6
|
+
def visit_Arel_Nodes_InsertStatement(o, collector)
|
7
|
+
collector << "INSERT INTO "
|
8
|
+
collector = visit o.relation, collector
|
9
|
+
|
10
|
+
unless o.columns.empty?
|
11
|
+
collector << " ("
|
12
|
+
o.columns.each_with_index do |x, i|
|
13
|
+
collector << ", " unless i == 0
|
14
|
+
collector << quote_column_name(x.name)
|
15
|
+
end
|
16
|
+
collector << ")"
|
17
|
+
end
|
18
|
+
|
19
|
+
if o.values
|
20
|
+
maybe_visit o.values, collector
|
21
|
+
elsif o.select
|
22
|
+
maybe_visit o.select, collector
|
23
|
+
else
|
24
|
+
collector
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def visit_Arel_Nodes_SelectStatement(o, collector)
|
29
|
+
collector << 'SELECT '
|
30
|
+
collector = visit o.offset, collector if o.offset && !o.limit
|
31
|
+
|
32
|
+
collector = o.cores.inject(collector) do |c, x|
|
33
|
+
visit_Arel_Nodes_SelectCore(x, c)
|
34
|
+
end
|
35
|
+
|
36
|
+
unless o.orders.empty?
|
37
|
+
collector << ORDER_BY
|
38
|
+
len = o.orders.length - 1
|
39
|
+
o.orders.each_with_index do |x, i|
|
40
|
+
collector = visit(x, collector)
|
41
|
+
collector << COMMA unless len == i
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if o.limit && o.offset
|
46
|
+
collector = limit_with_rows o, collector
|
47
|
+
elsif o.limit && !o.offset
|
48
|
+
collector = visit o.limit, collector
|
49
|
+
end
|
50
|
+
|
51
|
+
maybe_visit o.lock, collector
|
52
|
+
end
|
53
|
+
|
54
|
+
def visit_Arel_Nodes_SelectCore(o, collector)
|
55
|
+
if o.set_quantifier
|
56
|
+
collector = visit o.set_quantifier, collector
|
57
|
+
collector << SPACE
|
58
|
+
end
|
59
|
+
|
60
|
+
unless o.projections.empty?
|
61
|
+
len = o.projections.length - 1
|
62
|
+
o.projections.each_with_index do |x, i|
|
63
|
+
collector = visit(x, collector)
|
64
|
+
collector << COMMA unless len == i
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if o.source && !o.source.empty?
|
69
|
+
collector << ' FROM '
|
70
|
+
collector = visit o.source, collector
|
71
|
+
end
|
72
|
+
|
73
|
+
unless o.wheres.empty?
|
74
|
+
collector << WHERE
|
75
|
+
len = o.wheres.length - 1
|
76
|
+
o.wheres.each_with_index do |x, i|
|
77
|
+
collector = visit(x, collector)
|
78
|
+
collector << AND unless len == i
|
79
|
+
end
|
80
|
+
end
|
81
|
+
unless o.groups.empty?
|
82
|
+
collector << GROUP_BY
|
83
|
+
len = o.groups.length - 1
|
84
|
+
o.groups.each_with_index do |x, i|
|
85
|
+
collector = visit(x, collector)
|
86
|
+
collector << COMMA unless len == i
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
if Rails::VERSION::MAJOR < 5
|
91
|
+
collector = maybe_visit o.having, collector
|
92
|
+
else
|
93
|
+
unless o.havings.empty?
|
94
|
+
collector << ' HAVING '
|
95
|
+
inject_join o.havings, collector, AND
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
collector
|
100
|
+
end
|
101
|
+
|
102
|
+
def visit_Arel_Nodes_Limit(o, collector)
|
103
|
+
collector << ' ROWS '
|
104
|
+
visit o.expr, collector
|
105
|
+
end
|
106
|
+
|
107
|
+
def visit_Arel_Nodes_Offset(o, collector)
|
108
|
+
collector << ' SKIP '
|
109
|
+
visit o.expr, collector
|
110
|
+
end
|
111
|
+
|
112
|
+
def limit_with_rows o, collector
|
113
|
+
o.offset.expr.value = ActiveModel::Attribute.with_cast_value('OFFSET'.freeze,
|
114
|
+
o.offset.expr.value.value + 1,
|
115
|
+
ActiveModel::Type.default_value)
|
116
|
+
offset = o.offset.expr.value
|
117
|
+
o.limit.expr.value = ActiveModel::Attribute.with_cast_value('LIMIT'.freeze,
|
118
|
+
o.limit.expr.value.value + (offset.value - 1),
|
119
|
+
ActiveModel::Type.default_value)
|
120
|
+
limit = o.limit.expr.value
|
121
|
+
collector << ' ROWS '
|
122
|
+
collector.add_bind(offset) { |i| '?' }
|
123
|
+
collector << ' TO '
|
124
|
+
collector.add_bind(limit) { |i| '?' }
|
125
|
+
end
|
126
|
+
|
127
|
+
def quote_column_name name
|
128
|
+
return name if Arel::Nodes::SqlLiteral === name
|
129
|
+
|
130
|
+
@connection.quote_column_name(name)
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|