activerecord-rdb-adapter 0.9.4 → 0.9.6.beta2

Sign up to get free protection for your applications and to get access to all the features.
data/fb_extensions.rb CHANGED
@@ -1,21 +1,21 @@
1
- module Fb
2
- class Connection
3
- def execute_script(sql)
4
- stmts = []
5
- delim = ';'
6
- while sql =~ /\S/
7
- stmt, sql = sql.split(delim, 2)
8
- if stmt =~ /^\s*set\s+term\s+(\S+)/i
9
- delim = $1
10
- elsif stmt =~ /\S/
11
- stmts << stmt
12
- end
13
- end
14
- self.transaction do
15
- stmts.each do |stmt|
16
- self.execute(stmt)
17
- end
18
- end
19
- end
20
- end
21
- end
1
+ module Fb
2
+ class Connection
3
+ def execute_script(sql)
4
+ stmts = []
5
+ delim = ';'
6
+ while sql =~ /\S/
7
+ stmt, sql = sql.split(delim, 2)
8
+ if stmt =~ /^\s*set\s+term\s+(\S+)/i
9
+ delim = $1
10
+ elsif stmt =~ /\S/
11
+ stmts << stmt
12
+ end
13
+ end
14
+ self.transaction do
15
+ stmts.each do |stmt|
16
+ self.execute(stmt)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,68 +1,68 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveModel
4
- module Type
5
- class Integer < Value # :nodoc:
6
- include Helpers::Numeric
7
-
8
- DEFAULT_LIMIT = 8
9
-
10
- def initialize(*)
11
- super
12
- @range = min_value...max_value
13
- end
14
-
15
- def type
16
- :integer
17
- end
18
-
19
- def deserialize(value)
20
- return if value.nil?
21
- value.to_i
22
- end
23
-
24
- def serialize(value)
25
- result = cast(value)
26
- if result
27
- ensure_in_range(result)
28
- end
29
- result
30
- end
31
-
32
- # TODO Change this to private once we've dropped Ruby 2.2 support.
33
- # Workaround for Ruby 2.2 "private attribute?" warning.
34
- protected
35
-
36
- attr_reader :range
37
-
38
- private
39
-
40
- def cast_value(value)
41
- case value
42
- when true then 1
43
- when false then 0
44
- else
45
- value.to_i rescue nil
46
- end
47
- end
48
-
49
- def ensure_in_range(value)
50
- unless range.cover?(value)
51
- raise ActiveModel::RangeError, "#{value} is out of range for #{self.class} with limit #{_limit} bytes"
52
- end
53
- end
54
-
55
- def max_value
56
- 1 << (_limit * 8 - 1) # 8 bits per byte with one bit for sign
57
- end
58
-
59
- def min_value
60
- -max_value
61
- end
62
-
63
- def _limit
64
- limit || DEFAULT_LIMIT
65
- end
66
- end
67
- end
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModel
4
+ module Type
5
+ class Integer < Value # :nodoc:
6
+ include Helpers::Numeric
7
+
8
+ DEFAULT_LIMIT = 8
9
+
10
+ def initialize(*)
11
+ super
12
+ @range = min_value...max_value
13
+ end
14
+
15
+ def type
16
+ :integer
17
+ end
18
+
19
+ def deserialize(value)
20
+ return if value.nil?
21
+ value.to_i
22
+ end
23
+
24
+ def serialize(value)
25
+ result = cast(value)
26
+ if result
27
+ ensure_in_range(result)
28
+ end
29
+ result
30
+ end
31
+
32
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
33
+ # Workaround for Ruby 2.2 "private attribute?" warning.
34
+ protected
35
+
36
+ attr_reader :range
37
+
38
+ private
39
+
40
+ def cast_value(value)
41
+ case value
42
+ when true then 1
43
+ when false then 0
44
+ else
45
+ value.to_i rescue nil
46
+ end
47
+ end
48
+
49
+ def ensure_in_range(value)
50
+ unless range.cover?(value)
51
+ raise ActiveModel::RangeError, "#{value} is out of range for #{self.class} with limit #{_limit} bytes"
52
+ end
53
+ end
54
+
55
+ def max_value
56
+ 1 << (_limit * 8 - 1) # 8 bits per byte with one bit for sign
57
+ end
58
+
59
+ def min_value
60
+ -max_value
61
+ end
62
+
63
+ def _limit
64
+ limit || DEFAULT_LIMIT
65
+ end
66
+ end
67
+ end
68
68
  end
@@ -1,35 +1,35 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- module Rdb
4
- module DatabaseLimits # :nodoc:
5
- def table_alias_length
6
- 31
7
- end
8
-
9
- def column_name_length
10
- 31
11
- end
12
-
13
- def table_name_length
14
- 31
15
- end
16
-
17
- def index_name_length
18
- 31
19
- end
20
-
21
- def indexes_per_table
22
- 65_535
23
- end
24
-
25
- def in_clause_length
26
- 1_499
27
- end
28
-
29
- def sql_query_length
30
- 32_767
31
- end
32
- end
33
- end
34
- end
35
- end
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Rdb
4
+ module DatabaseLimits # :nodoc:
5
+ def table_alias_length
6
+ 31
7
+ end
8
+
9
+ def column_name_length
10
+ 31
11
+ end
12
+
13
+ def table_name_length
14
+ 31
15
+ end
16
+
17
+ def index_name_length
18
+ 31
19
+ end
20
+
21
+ def indexes_per_table
22
+ 65_535
23
+ end
24
+
25
+ def in_clause_length
26
+ 1_499
27
+ end
28
+
29
+ def sql_query_length
30
+ 32_767
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,183 +1,186 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- module Rdb
4
- module DatabaseStatements # :nodoc:
5
- def execute(sql, name = nil)
6
- log(sql, name) do
7
- ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
8
- @connection.query(sql)
9
- end
10
- end
11
- end
12
-
13
- def exec_query(sql, name = 'SQL', binds = [], prepare: false)
14
- type_casted_binds = type_casted_binds(binds)
15
-
16
- log(sql, name, binds, type_casted_binds) do
17
- ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
18
- result = @connection.execute(sql, *type_casted_binds)
19
- if result.is_a?(Fb::Cursor)
20
- fields = result.fields.map(&:name)
21
- rows = result.fetchall.map do |row|
22
- row.map do |col|
23
- col.encode('UTF-8', @connection.encoding)
24
- rescue StandardError
25
- col
26
- end
27
- end
28
- result.close
29
- ActiveRecord::Result.new(fields, rows)
30
- else
31
- result
32
- end
33
- end
34
- end
35
- rescue StandardError => e
36
- raise e
37
- end
38
-
39
- def explain(arel, binds = [])
40
- to_sql(arel, binds)
41
- end
42
-
43
- # Begins the transaction (and turns off auto-committing).
44
- def begin_db_transaction
45
- log('begin transaction', nil) do
46
- begin_isolated_db_transaction(default_transaction_isolation)
47
- end
48
- end
49
-
50
- # Default isolation levels for transactions. This method exists
51
- # in 4.0.2+, so it's here for backward compatibility with AR 3
52
- def transaction_isolation_levels
53
- {
54
- read_committed: 'READ COMMITTED',
55
- repeatable_read: 'REPEATABLE READ',
56
- serializable: 'SERIALIZABLE'
57
- }
58
- end
59
-
60
- # Allows providing the :transaction option to ActiveRecord::Base.transaction
61
- # in 4.0.2+. Can accept verbatim isolation options like 'WAIT READ COMMITTED'
62
- def begin_isolated_db_transaction(isolation)
63
- @connection.transaction transaction_isolation_levels.fetch(isolation, isolation)
64
- end
65
-
66
- # Commits the transaction (and turns on auto-committing).
67
- def commit_db_transaction
68
- log('commit transaction', nil) { @connection.commit }
69
- end
70
-
71
- # Rolls back the transaction (and turns on auto-committing). Must be
72
- # done if the transaction block raises an exception or returns false.
73
- def rollback_db_transaction
74
- log('rollback transaction', nil) { @connection.rollback }
75
- end
76
-
77
- def default_sequence_name(table_name, _column = nil)
78
- "#{table_name.to_s.tr('-', '_')[0, table_name_length - 4]}_seq"
79
- end
80
-
81
- # Set the sequence to the max value of the table's column.
82
- def reset_sequence!(table, column, sequence = nil)
83
- sequence ||= default_sequence_name(table, column)
84
- max_id = select_value("select max(#{column}) from #{table}")
85
- execute("alter sequence #{sequence} restart with #{max_id}")
86
- end
87
-
88
- # Uses the raw connection to get the next sequence value.
89
- def next_sequence_value(sequence_name)
90
- @connection.query("SELECT NEXT VALUE FOR #{sequence_name} FROM RDB$DATABASE")[0][0]
91
- end
92
-
93
- def last_inserted_id(_result)
94
- nil
95
- end
96
-
97
- def insert_fixtures_set(fixture_set, tables_to_delete = [])
98
- fixture_inserts = fixture_set.map do |table_name, fixtures|
99
- next if fixtures.empty?
100
-
101
- build_fixture_sql(fixtures, table_name).collect {|f| f }
102
- end.compact
103
-
104
- table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
105
- sql = fixture_inserts.flatten(1)
106
- sql.unshift(*table_deletes)
107
-
108
- transaction(requires_new: true) do
109
- sql.each do |s|
110
- execute s, 'Fixture load'
111
- end
112
- end
113
- end
114
-
115
- private
116
-
117
- def default_insert_value(column)
118
- if column.default.nil?
119
- Arel.sql('NULL')
120
- else
121
- Arel.sql(quote(column.default))
122
- end
123
- end
124
-
125
- def build_fixture_sql(fixtures, table_name)
126
- columns = schema_cache.columns_hash(table_name)
127
-
128
- values = fixtures.map do |fixture|
129
- fixture = fixture.stringify_keys
130
-
131
- unknown_columns = fixture.keys - columns.keys
132
- if unknown_columns.any?
133
- raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
134
- end
135
-
136
- columns.map do |name, column|
137
- if fixture.key?(name)
138
- type = lookup_cast_type_from_column(column)
139
- bind = Relation::QueryAttribute.new(name, fixture[name], type)
140
- with_yaml_fallback(bind.value_for_database)
141
- else
142
- default_insert_value(column)
143
- end
144
- end
145
- end
146
-
147
- sql ||= []
148
-
149
- values.each_with_index do |row, i|
150
- s = ''
151
- s << "INSERT INTO #{quote_table_name(table_name)}"
152
-
153
- unless columns.empty?
154
- s << ' ('
155
- columns.each_with_index do |x, y|
156
- s << ', ' unless y == 0
157
- s << quote_column_name(x[1].name)
158
- end
159
- s << ')'
160
- end
161
-
162
- s << ' VALUES ('
163
- row.each_with_index do |value, k|
164
- s << ', ' unless k == 0
165
- case value
166
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
167
- s << value.to_s
168
- when Time
169
- s << quote(value.strftime("%F %T"))
170
- else
171
- s << quote(value).to_s
172
- end
173
- end
174
- s << ');'
175
- sql << s
176
- end
177
-
178
- sql
179
- end
180
- end
181
- end
182
- end
183
- end
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Rdb
4
+ module DatabaseStatements # :nodoc:
5
+ def execute(sql, name = nil)
6
+ log(sql, name) do
7
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
8
+ @connection.query(sql)
9
+ end
10
+ end
11
+ end
12
+
13
+ def exec_query(sql, name = 'SQL', binds = [], prepare: false)
14
+ type_casted_binds = type_casted_binds(binds)
15
+
16
+ log(sql, name, binds, type_casted_binds) do
17
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
18
+ result = @connection.execute(sql, *type_casted_binds)
19
+ if result.is_a?(Fb::Cursor)
20
+ fields = result.fields.map(&:name)
21
+ rows = result.fetchall.map do |row|
22
+ row.map do |col|
23
+ col.encode('UTF-8', @connection.encoding)
24
+ rescue StandardError
25
+ col
26
+ end
27
+ end
28
+ result.close
29
+ ActiveRecord::Result.new(fields, rows)
30
+ else
31
+ result
32
+ end
33
+ rescue => e
34
+ result.close if result && result.is_a?(Fb::Cursor)
35
+ raise e
36
+ end
37
+ end
38
+ rescue => e
39
+ raise e
40
+ end
41
+
42
+ def explain(arel, binds = [])
43
+ to_sql(arel, binds)
44
+ end
45
+
46
+ # Begins the transaction (and turns off auto-committing).
47
+ def begin_db_transaction
48
+ log('begin transaction', nil) do
49
+ begin_isolated_db_transaction(default_transaction_isolation)
50
+ end
51
+ end
52
+
53
+ # Default isolation levels for transactions. This method exists
54
+ # in 4.0.2+, so it's here for backward compatibility with AR 3
55
+ def transaction_isolation_levels
56
+ {
57
+ read_committed: 'READ COMMITTED',
58
+ repeatable_read: 'REPEATABLE READ',
59
+ serializable: 'SERIALIZABLE'
60
+ }
61
+ end
62
+
63
+ # Allows providing the :transaction option to ActiveRecord::Base.transaction
64
+ # in 4.0.2+. Can accept verbatim isolation options like 'WAIT READ COMMITTED'
65
+ def begin_isolated_db_transaction(isolation)
66
+ @connection.transaction transaction_isolation_levels.fetch(isolation, isolation)
67
+ end
68
+
69
+ # Commits the transaction (and turns on auto-committing).
70
+ def commit_db_transaction
71
+ log('commit transaction', nil) { @connection.commit }
72
+ end
73
+
74
+ # Rolls back the transaction (and turns on auto-committing). Must be
75
+ # done if the transaction block raises an exception or returns false.
76
+ def rollback_db_transaction
77
+ log('rollback transaction', nil) { @connection.rollback }
78
+ end
79
+
80
+ def default_sequence_name(table_name, _column = nil)
81
+ "#{table_name.to_s.tr('-', '_')[0, table_name_length - 4]}_seq"
82
+ end
83
+
84
+ # Set the sequence to the max value of the table's column.
85
+ def reset_sequence!(table, column, sequence = nil)
86
+ sequence ||= default_sequence_name(table, column)
87
+ max_id = select_value("select max(#{column}) from #{table}")
88
+ execute("alter sequence #{sequence} restart with #{max_id}")
89
+ end
90
+
91
+ # Uses the raw connection to get the next sequence value.
92
+ def next_sequence_value(sequence_name)
93
+ @connection.query("SELECT NEXT VALUE FOR #{sequence_name} FROM RDB$DATABASE")[0][0]
94
+ end
95
+
96
+ def last_inserted_id(_result)
97
+ nil
98
+ end
99
+
100
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
101
+ fixture_inserts = fixture_set.map do |table_name, fixtures|
102
+ next if fixtures.empty?
103
+
104
+ build_fixture_sql(fixtures, table_name).collect {|f| f }
105
+ end.compact
106
+
107
+ table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
108
+ sql = fixture_inserts.flatten(1)
109
+ sql.unshift(*table_deletes)
110
+
111
+ transaction(requires_new: true) do
112
+ sql.each do |s|
113
+ execute s, 'Fixture load'
114
+ end
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ def default_insert_value(column)
121
+ if column.default.nil?
122
+ Arel.sql('NULL')
123
+ else
124
+ Arel.sql(quote(column.default))
125
+ end
126
+ end
127
+
128
+ def build_fixture_sql(fixtures, table_name)
129
+ columns = schema_cache.columns_hash(table_name)
130
+
131
+ values = fixtures.map do |fixture|
132
+ fixture = fixture.stringify_keys
133
+
134
+ unknown_columns = fixture.keys - columns.keys
135
+ if unknown_columns.any?
136
+ raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
137
+ end
138
+
139
+ columns.map do |name, column|
140
+ if fixture.key?(name)
141
+ type = lookup_cast_type_from_column(column)
142
+ bind = Relation::QueryAttribute.new(name, fixture[name], type)
143
+ with_yaml_fallback(bind.value_for_database)
144
+ else
145
+ default_insert_value(column)
146
+ end
147
+ end
148
+ end
149
+
150
+ sql ||= []
151
+
152
+ values.each_with_index do |row, i|
153
+ s = ''
154
+ s << "INSERT INTO #{quote_table_name(table_name)}"
155
+
156
+ unless columns.empty?
157
+ s << ' ('
158
+ columns.each_with_index do |x, y|
159
+ s << ', ' unless y == 0
160
+ s << quote_column_name(x[1].name)
161
+ end
162
+ s << ')'
163
+ end
164
+
165
+ s << ' VALUES ('
166
+ row.each_with_index do |value, k|
167
+ s << ', ' unless k == 0
168
+ case value
169
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
170
+ s << value.to_s
171
+ when Time
172
+ s << quote(value.strftime("%F %T"))
173
+ else
174
+ s << quote(value).to_s
175
+ end
176
+ end
177
+ s << ');'
178
+ sql << s
179
+ end
180
+
181
+ sql
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end