pmacs-activerecord-oracle_enhanced-adapter 1.4.2.rc1 → 1.5.5.1
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 +7 -0
- data/Gemfile +11 -40
- data/History.md +170 -0
- data/README.md +61 -5
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +330 -161
- data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +48 -8
- data/lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb +77 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +8 -24
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +4 -13
- data/lib/active_record/connection_adapters/oracle_enhanced_database_tasks.rb +61 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +13 -12
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +42 -19
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +28 -74
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +165 -231
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_creation.rb +89 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +16 -24
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +29 -38
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +93 -42
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +5 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +7 -7
- data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -1
- data/lib/pmacs-activerecord-oracle_enhanced-adapter.rb +2 -2
- data/pmacs-activerecord-oracle_enhanced-adapter.gemspec +19 -17
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +35 -99
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +17 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +105 -98
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +74 -44
- data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +89 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +3 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +13 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +11 -12
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +252 -60
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +170 -40
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +14 -8
- data/spec/spec_helper.rb +25 -54
- metadata +41 -72
- data/lib/active_record/connection_adapters/oracle_enhanced.rake +0 -105
- data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
- data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -118
- data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +0 -25
- data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
- data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +0 -19
@@ -0,0 +1,89 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class OracleEnhancedAdapter < AbstractAdapter
|
4
|
+
class SchemaCreation < AbstractAdapter::SchemaCreation
|
5
|
+
private
|
6
|
+
|
7
|
+
def visit_ColumnDefinition(o)
|
8
|
+
if o.type.to_sym == :virtual
|
9
|
+
sql_type = type_to_sql(o.default[:type], o.limit, o.precision, o.scale) if o.default[:type]
|
10
|
+
"#{quote_column_name(o.name)} #{sql_type} AS (#{o.default[:as]})"
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def visit_TableDefinition(o)
|
17
|
+
tablespace = tablespace_for(:table, o.options[:tablespace])
|
18
|
+
create_sql = "CREATE#{' GLOBAL TEMPORARY' if o.temporary} TABLE "
|
19
|
+
create_sql << "#{quote_table_name(o.name)} ("
|
20
|
+
create_sql << o.columns.map { |c| accept c }.join(', ')
|
21
|
+
create_sql << ")"
|
22
|
+
unless o.temporary
|
23
|
+
create_sql << " ORGANIZATION #{o.options[:organization]}" if o.options[:organization]
|
24
|
+
create_sql << "#{tablespace}"
|
25
|
+
end
|
26
|
+
create_sql << " #{o.options[:options]}"
|
27
|
+
create_sql
|
28
|
+
end
|
29
|
+
|
30
|
+
def tablespace_for(obj_type, tablespace_option, table_name=nil, column_name=nil)
|
31
|
+
tablespace_sql = ''
|
32
|
+
if tablespace = (tablespace_option || default_tablespace_for(obj_type))
|
33
|
+
tablespace_sql << if [:blob, :clob].include?(obj_type.to_sym)
|
34
|
+
" LOB (#{quote_column_name(column_name)}) STORE AS #{column_name.to_s[0..10]}_#{table_name.to_s[0..14]}_ls (TABLESPACE #{tablespace})"
|
35
|
+
else
|
36
|
+
" TABLESPACE #{tablespace}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
tablespace_sql
|
40
|
+
end
|
41
|
+
|
42
|
+
def default_tablespace_for(type)
|
43
|
+
(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[type] ||
|
44
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[native_database_types[type][:name]]) rescue nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def foreign_key_definition(to_table, options = {})
|
48
|
+
@conn.foreign_key_definition(to_table, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_column_options!(sql, options)
|
52
|
+
type = options[:type] || ((column = options[:column]) && column.type)
|
53
|
+
type = type && type.to_sym
|
54
|
+
# handle case of defaults for CLOB columns, which would otherwise get "quoted" incorrectly
|
55
|
+
if options_include_default?(options)
|
56
|
+
if type == :text
|
57
|
+
sql << " DEFAULT #{@conn.quote(options[:default])}"
|
58
|
+
else
|
59
|
+
# from abstract adapter
|
60
|
+
sql << " DEFAULT #{@conn.quote(options[:default], options[:column])}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
# must explicitly add NULL or NOT NULL to allow change_column to work on migrations
|
64
|
+
if options[:null] == false
|
65
|
+
sql << " NOT NULL"
|
66
|
+
elsif options[:null] == true
|
67
|
+
sql << " NULL" unless type == :primary_key
|
68
|
+
end
|
69
|
+
# add AS expression for virtual columns
|
70
|
+
if options[:as].present?
|
71
|
+
sql << " AS (#{options[:as]})"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# This method does not exist in SchemaCreation at Rails 4.0
|
76
|
+
# It can be removed only when Oracle enhanced adapter supports Rails 4.1 and higher
|
77
|
+
def options_include_default?(options)
|
78
|
+
options.include?(:default) && !(options[:null] == false && options[:default].nil?)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def schema_creation
|
84
|
+
SchemaCreation.new self
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -13,8 +13,8 @@ module ActiveRecord
|
|
13
13
|
module OracleEnhancedColumnDefinition
|
14
14
|
def self.included(base) #:nodoc:
|
15
15
|
base.class_eval do
|
16
|
-
alias_method_chain :to_sql, :virtual_columns
|
17
|
-
alias to_s :to_sql
|
16
|
+
#alias_method_chain :to_sql, :virtual_columns
|
17
|
+
#alias to_s :to_sql
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -42,10 +42,6 @@ module ActiveRecord
|
|
42
42
|
include OracleEnhancedTableDefinition
|
43
43
|
end
|
44
44
|
|
45
|
-
base::ColumnDefinition.class_eval do
|
46
|
-
include OracleEnhancedColumnDefinition
|
47
|
-
end
|
48
|
-
|
49
45
|
# Available starting from ActiveRecord 2.1
|
50
46
|
base::Table.class_eval do
|
51
47
|
include OracleEnhancedTable
|
@@ -64,8 +60,6 @@ module ActiveRecord
|
|
64
60
|
def self.included(base) #:nodoc:
|
65
61
|
base.class_eval do
|
66
62
|
alias_method_chain :references, :foreign_keys
|
67
|
-
alias_method_chain :to_sql, :foreign_keys
|
68
|
-
|
69
63
|
alias_method_chain :column, :virtual_columns
|
70
64
|
end
|
71
65
|
end
|
@@ -110,11 +104,15 @@ module ActiveRecord
|
|
110
104
|
# Note: If no name is specified, the database driver creates one for you!
|
111
105
|
def references_with_foreign_keys(*args)
|
112
106
|
options = args.extract_options!
|
107
|
+
index_options = options[:index]
|
113
108
|
fk_options = options.delete(:foreign_key)
|
114
109
|
|
115
110
|
if fk_options && !options[:polymorphic]
|
116
111
|
fk_options = {} if fk_options == true
|
117
|
-
args.each
|
112
|
+
args.each do |to_table|
|
113
|
+
foreign_key(to_table, fk_options)
|
114
|
+
add_index(to_table, "#{to_table}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
|
115
|
+
end
|
118
116
|
end
|
119
117
|
|
120
118
|
references_without_foreign_keys(*(args << options))
|
@@ -133,7 +131,8 @@ module ActiveRecord
|
|
133
131
|
# ====== Defining the column of the +to_table+.
|
134
132
|
# t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
|
135
133
|
def foreign_key(to_table, options = {})
|
136
|
-
|
134
|
+
#TODO
|
135
|
+
if ActiveRecord::Base.connection.supports_foreign_keys?
|
137
136
|
to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
|
138
137
|
foreign_keys << ForeignKey.new(@base, to_table, options)
|
139
138
|
else
|
@@ -141,20 +140,9 @@ module ActiveRecord
|
|
141
140
|
end
|
142
141
|
end
|
143
142
|
|
144
|
-
def
|
145
|
-
|
146
|
-
sql << ', ' << (foreign_keys * ', ') unless foreign_keys.blank?
|
147
|
-
sql
|
143
|
+
def foreign_keys
|
144
|
+
@foreign_keys ||= []
|
148
145
|
end
|
149
|
-
|
150
|
-
def lob_columns
|
151
|
-
columns.select(&:lob?)
|
152
|
-
end
|
153
|
-
|
154
|
-
private
|
155
|
-
def foreign_keys
|
156
|
-
@foreign_keys ||= []
|
157
|
-
end
|
158
146
|
end
|
159
147
|
|
160
148
|
module OracleEnhancedTable
|
@@ -212,6 +200,7 @@ module ActiveRecord
|
|
212
200
|
def references_with_foreign_keys(*args)
|
213
201
|
options = args.extract_options!
|
214
202
|
polymorphic = options[:polymorphic]
|
203
|
+
index_options = options[:index]
|
215
204
|
fk_options = options.delete(:foreign_key)
|
216
205
|
|
217
206
|
references_without_foreign_keys(*(args << options))
|
@@ -219,7 +208,10 @@ module ActiveRecord
|
|
219
208
|
args.extract_options!
|
220
209
|
if fk_options && !polymorphic
|
221
210
|
fk_options = {} if fk_options == true
|
222
|
-
args.each
|
211
|
+
args.each do |to_table|
|
212
|
+
foreign_key(to_table, fk_options)
|
213
|
+
add_index(to_table, "#{to_table}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
|
214
|
+
end
|
223
215
|
end
|
224
216
|
end
|
225
217
|
end
|
@@ -13,10 +13,10 @@ module ActiveRecord #:nodoc:
|
|
13
13
|
private
|
14
14
|
|
15
15
|
def ignore_table?(table)
|
16
|
-
[
|
16
|
+
['schema_migrations', ignore_tables].flatten.any? do |ignored|
|
17
17
|
case ignored
|
18
|
-
when String; table == ignored
|
19
|
-
when Regexp; table =~ ignored
|
18
|
+
when String; remove_prefix_and_suffix(table) == ignored
|
19
|
+
when Regexp; remove_prefix_and_suffix(table) =~ ignored
|
20
20
|
else
|
21
21
|
raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.'
|
22
22
|
end
|
@@ -51,7 +51,7 @@ module ActiveRecord #:nodoc:
|
|
51
51
|
if @connection.respond_to?(:has_primary_key_trigger?) && @connection.has_primary_key_trigger?(table_name)
|
52
52
|
pk, pk_seq = @connection.pk_and_sequence_for(table_name)
|
53
53
|
stream.print " add_primary_key_trigger #{table_name.inspect}"
|
54
|
-
stream.print ", :
|
54
|
+
stream.print ", primary_key: \"#{pk}\"" if pk != 'id'
|
55
55
|
stream.print "\n\n"
|
56
56
|
end
|
57
57
|
end
|
@@ -61,24 +61,24 @@ module ActiveRecord #:nodoc:
|
|
61
61
|
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
62
62
|
statement_parts = [ ('add_foreign_key ' + foreign_key.from_table.inspect) ]
|
63
63
|
statement_parts << foreign_key.to_table.inspect
|
64
|
-
|
64
|
+
|
65
65
|
if foreign_key.options[:columns].size == 1
|
66
66
|
column = foreign_key.options[:columns].first
|
67
67
|
if column != "#{foreign_key.to_table.singularize}_id"
|
68
|
-
statement_parts << (':
|
68
|
+
statement_parts << ('column: ' + column.inspect)
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
if foreign_key.options[:references].first != 'id'
|
72
|
-
statement_parts << (':
|
72
|
+
statement_parts << ('primary_key: ' + foreign_key.options[:references].first.inspect)
|
73
73
|
end
|
74
74
|
else
|
75
|
-
statement_parts << (':
|
75
|
+
statement_parts << ('columns: ' + foreign_key.options[:columns].inspect)
|
76
76
|
end
|
77
77
|
|
78
|
-
statement_parts << (':
|
78
|
+
statement_parts << ('name: ' + foreign_key.options[:name].inspect)
|
79
79
|
|
80
80
|
unless foreign_key.options[:dependent].blank?
|
81
|
-
statement_parts << (':
|
81
|
+
statement_parts << ('dependent: ' + foreign_key.options[:dependent].inspect)
|
82
82
|
end
|
83
83
|
|
84
84
|
' ' + statement_parts.join(', ')
|
@@ -97,7 +97,7 @@ module ActiveRecord #:nodoc:
|
|
97
97
|
table_name = syn.table_name
|
98
98
|
table_name = "#{syn.table_owner}.#{table_name}" if syn.table_owner
|
99
99
|
table_name = "#{table_name}@#{syn.db_link}" if syn.db_link
|
100
|
-
stream.print " add_synonym #{syn.name.inspect}, #{table_name.inspect}, :
|
100
|
+
stream.print " add_synonym #{syn.name.inspect}, #{table_name.inspect}, force: true"
|
101
101
|
stream.puts
|
102
102
|
end
|
103
103
|
stream.puts unless syns.empty?
|
@@ -118,9 +118,9 @@ module ActiveRecord #:nodoc:
|
|
118
118
|
# use table.inspect as it will remove prefix and suffix
|
119
119
|
statement_parts = [ ('add_index ' + table.inspect) ]
|
120
120
|
statement_parts << index.columns.inspect
|
121
|
-
statement_parts << (':
|
122
|
-
statement_parts << ':
|
123
|
-
statement_parts << ':
|
121
|
+
statement_parts << ('name: ' + index.name.inspect)
|
122
|
+
statement_parts << 'unique: true' if index.unique
|
123
|
+
statement_parts << 'tablespace: ' + index.tablespace.inspect if index.tablespace
|
124
124
|
when 'CTXSYS.CONTEXT'
|
125
125
|
if index.statement_parameters
|
126
126
|
statement_parts = [ ('add_context_index ' + table.inspect) ]
|
@@ -128,7 +128,7 @@ module ActiveRecord #:nodoc:
|
|
128
128
|
else
|
129
129
|
statement_parts = [ ('add_context_index ' + table.inspect) ]
|
130
130
|
statement_parts << index.columns.inspect
|
131
|
-
statement_parts << (':
|
131
|
+
statement_parts << ('name: ' + index.name.inspect)
|
132
132
|
end
|
133
133
|
else
|
134
134
|
# unrecognized index type
|
@@ -157,42 +157,30 @@ module ActiveRecord #:nodoc:
|
|
157
157
|
tbl.print " create_table #{table.inspect}"
|
158
158
|
|
159
159
|
# addition to make temporary option work
|
160
|
-
tbl.print ", :
|
160
|
+
tbl.print ", temporary: true" if @connection.temporary_table?(table)
|
161
161
|
|
162
162
|
if columns.detect { |c| c.name == pk }
|
163
163
|
if pk != 'id'
|
164
|
-
tbl.print %Q(, :
|
164
|
+
tbl.print %Q(, primary_key: "#{pk}")
|
165
165
|
end
|
166
166
|
else
|
167
|
-
tbl.print ", :
|
167
|
+
tbl.print ", id: false"
|
168
168
|
end
|
169
|
-
tbl.print ", :
|
169
|
+
tbl.print ", force: true"
|
170
170
|
tbl.puts " do |t|"
|
171
171
|
|
172
172
|
# then dump all non-primary key columns
|
173
173
|
column_specs = columns.map do |column|
|
174
174
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
|
175
175
|
next if column.name == pk
|
176
|
-
|
177
|
-
spec[:name] = column.name.inspect
|
178
|
-
spec[:type] = column.virtual? ? 'virtual' : column.type.to_s
|
179
|
-
spec[:type] = column.virtual? ? 'virtual' : column.type.to_s
|
180
|
-
spec[:virtual_type] = column.type.inspect if column.virtual?
|
181
|
-
spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && column.type != :decimal
|
182
|
-
spec[:precision] = column.precision.inspect if !column.precision.nil?
|
183
|
-
spec[:scale] = column.scale.inspect if !column.scale.nil?
|
184
|
-
spec[:null] = 'false' if !column.null
|
185
|
-
spec[:as] = column.virtual_column_data_default if column.virtual?
|
186
|
-
spec[:default] = default_string(column.default) if column.has_default? && !column.virtual?
|
187
|
-
(spec.keys - [:name, :type]).each do |k|
|
188
|
-
key_s = (k == :virtual_type ? ":type => " : "#{k.inspect} => ")
|
189
|
-
spec[k] = key_s + spec[k]
|
190
|
-
end
|
191
|
-
spec
|
176
|
+
@connection.column_spec(column, @types)
|
192
177
|
end.compact
|
193
178
|
|
194
179
|
# find all migration keys used in this table
|
195
|
-
|
180
|
+
#
|
181
|
+
# TODO `& column_specs.map(&:keys).flatten` should be executed
|
182
|
+
# in migration_keys_with_oracle_enhanced
|
183
|
+
keys = @connection.migration_keys & column_specs.map(&:keys).flatten
|
196
184
|
|
197
185
|
# figure out the lengths for each column based on above keys
|
198
186
|
lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }
|
@@ -230,7 +218,10 @@ module ActiveRecord #:nodoc:
|
|
230
218
|
|
231
219
|
stream
|
232
220
|
end
|
233
|
-
|
221
|
+
|
222
|
+
def remove_prefix_and_suffix(table)
|
223
|
+
table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2")
|
224
|
+
end
|
234
225
|
|
235
226
|
# remove table name prefix and suffix when doing #inspect (which is used in tables method)
|
236
227
|
module TableInspect #:nodoc:
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
require 'digest/sha1'
|
2
3
|
|
3
4
|
module ActiveRecord
|
@@ -22,11 +23,11 @@ module ActiveRecord
|
|
22
23
|
# end
|
23
24
|
#
|
24
25
|
# Create primary key trigger (so that you can skip primary key value in INSERT statement).
|
25
|
-
# By default trigger name will be "table_name_pkt", you can override the name with
|
26
|
+
# By default trigger name will be "table_name_pkt", you can override the name with
|
26
27
|
# :trigger_name option (but it is not recommended to override it as then this trigger will
|
27
28
|
# not be detected by ActiveRecord model and it will still do prefetching of sequence value).
|
28
29
|
# Example:
|
29
|
-
#
|
30
|
+
#
|
30
31
|
# create_table :users, :primary_key_trigger => true do |t|
|
31
32
|
# # ...
|
32
33
|
# end
|
@@ -37,12 +38,13 @@ module ActiveRecord
|
|
37
38
|
# t.string :first_name, :comment => “Given name”
|
38
39
|
# t.string :last_name, :comment => “Surname”
|
39
40
|
# end
|
40
|
-
|
41
|
-
def create_table(name, options = {}
|
41
|
+
|
42
|
+
def create_table(name, options = {})
|
42
43
|
create_sequence = options[:id] != false
|
43
44
|
column_comments = {}
|
44
|
-
|
45
|
-
|
45
|
+
temporary = options.delete(:temporary)
|
46
|
+
additional_options = options
|
47
|
+
table_definition = create_table_definition name, temporary, additional_options
|
46
48
|
table_definition.primary_key(options[:primary_key] || Base.get_primary_key(name.to_s.singularize)) unless options[:id] == false
|
47
49
|
|
48
50
|
# store that primary key was defined in create_table block
|
@@ -68,7 +70,7 @@ module ActiveRecord
|
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
71
|
-
|
73
|
+
yield table_definition if block_given?
|
72
74
|
create_sequence = create_sequence || table_definition.create_sequence
|
73
75
|
column_comments = table_definition.column_comments if table_definition.column_comments
|
74
76
|
tablespace = tablespace_for(:table, options[:tablespace])
|
@@ -77,35 +79,38 @@ module ActiveRecord
|
|
77
79
|
drop_table(name, options)
|
78
80
|
end
|
79
81
|
|
80
|
-
|
81
|
-
|
82
|
-
create_sql << " (#{table_definition.to_sql})"
|
83
|
-
unless options[:temporary]
|
84
|
-
create_sql << " ORGANIZATION #{options[:organization]}" if options[:organization]
|
85
|
-
create_sql << tablespace
|
86
|
-
table_definition.lob_columns.each{|cd| create_sql << tablespace_for(cd.sql_type.downcase.to_sym, nil, name, cd.name)}
|
87
|
-
end
|
88
|
-
create_sql << " #{options[:options]}"
|
89
|
-
execute create_sql
|
90
|
-
|
82
|
+
execute schema_creation.accept table_definition
|
83
|
+
|
91
84
|
create_sequence_and_trigger(name, options) if create_sequence
|
92
|
-
|
85
|
+
|
93
86
|
add_table_comment name, options[:comment]
|
94
87
|
column_comments.each do |column_name, comment|
|
95
88
|
add_comment name, column_name, comment
|
96
89
|
end
|
97
|
-
|
90
|
+
table_definition.indexes.each_pair { |c,o| add_index name, c, o }
|
91
|
+
|
92
|
+
unless table_definition.foreign_keys.nil?
|
93
|
+
table_definition.foreign_keys.each do |foreign_key|
|
94
|
+
add_foreign_key(table_definition.name, foreign_key.to_table, foreign_key.options)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def create_table_definition(name, temporary, options)
|
100
|
+
TableDefinition.new native_database_types, name, temporary, options
|
98
101
|
end
|
99
102
|
|
100
|
-
def rename_table(
|
103
|
+
def rename_table(table_name, new_name) #:nodoc:
|
101
104
|
if new_name.to_s.length > table_name_length
|
102
105
|
raise ArgumentError, "New table name '#{new_name}' is too long; the limit is #{table_name_length} characters"
|
103
106
|
end
|
104
107
|
if "#{new_name}_seq".to_s.length > sequence_name_length
|
105
108
|
raise ArgumentError, "New sequence name '#{new_name}_seq' is too long; the limit is #{sequence_name_length} characters"
|
106
109
|
end
|
107
|
-
execute "RENAME #{quote_table_name(
|
108
|
-
execute "RENAME #{quote_table_name("#{
|
110
|
+
execute "RENAME #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
|
111
|
+
execute "RENAME #{quote_table_name("#{table_name}_seq")} TO #{quote_table_name("#{new_name}_seq")}" rescue nil
|
112
|
+
|
113
|
+
rename_table_indexes(table_name, new_name)
|
109
114
|
end
|
110
115
|
|
111
116
|
def drop_table(name, options = {}) #:nodoc:
|
@@ -114,30 +119,74 @@ module ActiveRecord
|
|
114
119
|
execute "DROP SEQUENCE #{quote_table_name(seq_name)}" rescue nil
|
115
120
|
ensure
|
116
121
|
clear_table_columns_cache(name)
|
122
|
+
self.all_schema_indexes = nil
|
123
|
+
end
|
124
|
+
|
125
|
+
def initialize_schema_migrations_table
|
126
|
+
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
|
127
|
+
|
128
|
+
unless table_exists?(sm_table)
|
129
|
+
index_name = "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}"
|
130
|
+
if index_name.length > index_name_length
|
131
|
+
truncate_to = index_name_length - index_name.to_s.length - 1
|
132
|
+
truncated_name = "unique_schema_migrations"[0..truncate_to]
|
133
|
+
index_name = "#{Base.table_name_prefix}#{truncated_name}#{Base.table_name_suffix}"
|
134
|
+
end
|
135
|
+
|
136
|
+
create_table(sm_table, :id => false) do |schema_migrations_table|
|
137
|
+
schema_migrations_table.column :version, :string, :null => false
|
138
|
+
end
|
139
|
+
add_index sm_table, :version, :unique => true, :name => index_name
|
140
|
+
|
141
|
+
# Backwards-compatibility: if we find schema_info, assume we've
|
142
|
+
# migrated up to that point:
|
143
|
+
si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
|
144
|
+
if table_exists?(si_table)
|
145
|
+
ActiveSupport::Deprecation.warn "Usage of the schema table `#{si_table}` is deprecated. Please switch to using `schema_migrations` table"
|
146
|
+
|
147
|
+
old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
|
148
|
+
assume_migrated_upto_version(old_version)
|
149
|
+
drop_table(si_table)
|
150
|
+
end
|
151
|
+
end
|
117
152
|
end
|
118
153
|
|
119
154
|
# clear cached indexes when adding new index
|
120
155
|
def add_index(table_name, column_name, options = {}) #:nodoc:
|
121
156
|
column_names = Array(column_name)
|
122
|
-
index_name = index_name(table_name, :
|
157
|
+
index_name = index_name(table_name, column: column_names)
|
123
158
|
|
124
159
|
if Hash === options # legacy support, since this param was a string
|
160
|
+
options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :tablespace, :options, :using)
|
161
|
+
|
125
162
|
index_type = options[:unique] ? "UNIQUE" : ""
|
126
163
|
index_name = options[:name].to_s if options.key?(:name)
|
127
164
|
tablespace = tablespace_for(:index, options[:tablespace])
|
165
|
+
max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
|
166
|
+
additional_options = options[:options]
|
128
167
|
else
|
168
|
+
if options
|
169
|
+
message = "Passing a string as third argument of `add_index` is deprecated and will" +
|
170
|
+
" be removed in Rails 4.1." +
|
171
|
+
" Use add_index(#{table_name.inspect}, #{column_name.inspect}, unique: true) instead"
|
172
|
+
|
173
|
+
ActiveSupport::Deprecation.warn message
|
174
|
+
end
|
175
|
+
|
129
176
|
index_type = options
|
177
|
+
additional_options = nil
|
178
|
+
max_index_length = allowed_index_name_length
|
130
179
|
end
|
131
180
|
|
132
|
-
if index_name.to_s.length >
|
133
|
-
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{
|
181
|
+
if index_name.to_s.length > max_index_length
|
182
|
+
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters"
|
134
183
|
end
|
135
184
|
if index_name_exists?(table_name, index_name, false)
|
136
185
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
137
186
|
end
|
138
187
|
quoted_column_names = column_names.map { |e| quote_column_name_or_expression(e) }.join(", ")
|
139
188
|
|
140
|
-
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{
|
189
|
+
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{additional_options}"
|
141
190
|
ensure
|
142
191
|
self.all_schema_indexes = nil
|
143
192
|
end
|
@@ -147,6 +196,14 @@ module ActiveRecord
|
|
147
196
|
def remove_index(table_name, options = {}) #:nodoc:
|
148
197
|
index_name = index_name(table_name, options)
|
149
198
|
unless index_name_exists?(table_name, index_name, true)
|
199
|
+
# sometimes options can be String or Array with column names
|
200
|
+
options = {} unless options.is_a?(Hash)
|
201
|
+
if options.has_key? :name
|
202
|
+
options_without_column = options.dup
|
203
|
+
options_without_column.delete :column
|
204
|
+
index_name_without_column = index_name(table_name, options_without_column)
|
205
|
+
return index_name_without_column if index_name_exists?(table_name, index_name_without_column, false)
|
206
|
+
end
|
150
207
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
|
151
208
|
end
|
152
209
|
remove_index!(table_name, index_name)
|
@@ -166,10 +223,10 @@ module ActiveRecord
|
|
166
223
|
options = {} unless options.is_a?(Hash)
|
167
224
|
identifier_max_length = options[:identifier_max_length] || index_name_length
|
168
225
|
return default_name if default_name.length <= identifier_max_length
|
169
|
-
|
226
|
+
|
170
227
|
# remove 'index', 'on' and 'and' keywords
|
171
228
|
shortened_name = "i_#{table_name}_#{Array(options[:column]) * '_'}"
|
172
|
-
|
229
|
+
|
173
230
|
# leave just first three letters from each word
|
174
231
|
if shortened_name.length > identifier_max_length
|
175
232
|
shortened_name = shortened_name.split('_').map{|w| w[0,3]}.join('_')
|
@@ -221,6 +278,8 @@ module ActiveRecord
|
|
221
278
|
add_column_sql << tablespace_for((type_to_sql(type).downcase.to_sym), nil, table_name, column_name) if type
|
222
279
|
|
223
280
|
execute(add_column_sql)
|
281
|
+
|
282
|
+
create_sequence_and_trigger(table_name, options) if type && type.to_sym == :primary_key
|
224
283
|
ensure
|
225
284
|
clear_table_columns_cache(table_name)
|
226
285
|
end
|
@@ -266,25 +325,17 @@ module ActiveRecord
|
|
266
325
|
|
267
326
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
268
327
|
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} to #{quote_column_name(new_column_name)}"
|
328
|
+
self.all_schema_indexes = nil
|
329
|
+
rename_column_indexes(table_name, column_name, new_column_name)
|
269
330
|
ensure
|
270
331
|
clear_table_columns_cache(table_name)
|
271
332
|
end
|
272
333
|
|
273
|
-
def remove_column(table_name,
|
274
|
-
|
275
|
-
is_deprecated = (major == 3 and minor >= 2) or major > 3
|
276
|
-
|
277
|
-
if column_names.flatten! and is_deprecated
|
278
|
-
message = 'Passing array to remove_columns is deprecated, please use ' +
|
279
|
-
'multiple arguments, like: `remove_columns(:posts, :foo, :bar)`'
|
280
|
-
ActiveSupport::Deprecation.warn message, caller
|
281
|
-
end
|
282
|
-
|
283
|
-
column_names.each do |column_name|
|
284
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
|
285
|
-
end
|
334
|
+
def remove_column(table_name, column_name, type = nil, options = {}) #:nodoc:
|
335
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
|
286
336
|
ensure
|
287
337
|
clear_table_columns_cache(table_name)
|
338
|
+
self.all_schema_indexes = nil
|
288
339
|
end
|
289
340
|
|
290
341
|
def add_comment(table_name, column_name, comment) #:nodoc:
|