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.
@@ -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