activerecord-oracle_enhanced-adapter 1.4.3 → 5.2.0

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.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +1162 -2
  3. data/README.md +567 -155
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +3 -1
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +19 -0
  7. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +132 -0
  8. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +345 -0
  9. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +52 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +280 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +64 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +59 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +538 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +46 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +435 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +196 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +164 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +95 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +79 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +194 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +709 -0
  24. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +28 -0
  25. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +353 -0
  26. data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +33 -0
  27. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +3 -0
  28. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +385 -1083
  29. data/lib/active_record/type/oracle_enhanced/boolean.rb +20 -0
  30. data/lib/active_record/type/oracle_enhanced/integer.rb +15 -0
  31. data/lib/active_record/type/oracle_enhanced/json.rb +10 -0
  32. data/lib/active_record/type/oracle_enhanced/national_character_string.rb +26 -0
  33. data/lib/active_record/type/oracle_enhanced/national_character_text.rb +36 -0
  34. data/lib/active_record/type/oracle_enhanced/raw.rb +25 -0
  35. data/lib/active_record/type/oracle_enhanced/string.rb +29 -0
  36. data/lib/active_record/type/oracle_enhanced/text.rb +32 -0
  37. data/lib/active_record/type/oracle_enhanced/timestampltz.rb +25 -0
  38. data/lib/active_record/type/oracle_enhanced/timestamptz.rb +25 -0
  39. data/lib/activerecord-oracle_enhanced-adapter.rb +5 -13
  40. data/spec/active_record/connection_adapters/{oracle_enhanced_emulate_oracle_adapter_spec.rb → emulation/oracle_adapter_spec.rb} +5 -4
  41. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +469 -0
  42. data/spec/active_record/connection_adapters/{oracle_enhanced_context_index_spec.rb → oracle_enhanced/context_index_spec.rb} +140 -128
  43. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +112 -0
  44. data/spec/active_record/connection_adapters/{oracle_enhanced_dbms_output_spec.rb → oracle_enhanced/dbms_output_spec.rb} +13 -13
  45. data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +365 -0
  46. data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +196 -0
  47. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +492 -0
  48. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +1433 -0
  49. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +478 -0
  50. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +385 -550
  51. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +92 -1249
  52. data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
  53. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +208 -0
  54. data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +139 -0
  55. data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
  56. data/spec/active_record/oracle_enhanced/type/integer_spec.rb +91 -0
  57. data/spec/active_record/oracle_enhanced/type/json_spec.rb +57 -0
  58. data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +55 -0
  59. data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +230 -0
  60. data/spec/active_record/oracle_enhanced/type/raw_spec.rb +122 -0
  61. data/spec/active_record/oracle_enhanced/type/text_spec.rb +229 -0
  62. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +75 -0
  63. data/spec/spec_config.yaml.template +11 -0
  64. data/spec/spec_helper.rb +100 -93
  65. data/spec/support/alter_system_set_open_cursors.sql +1 -0
  66. data/spec/support/alter_system_user_password.sql +2 -0
  67. data/spec/support/create_oracle_enhanced_users.sql +31 -0
  68. metadata +105 -152
  69. data/.rspec +0 -2
  70. data/Gemfile +0 -52
  71. data/RUNNING_TESTS.md +0 -45
  72. data/Rakefile +0 -59
  73. data/activerecord-oracle_enhanced-adapter.gemspec +0 -130
  74. data/lib/active_record/connection_adapters/oracle_enhanced.rake +0 -105
  75. data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
  76. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -121
  77. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +0 -151
  78. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +0 -119
  79. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -359
  80. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +0 -25
  81. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +0 -21
  82. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -46
  83. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +0 -572
  84. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +0 -497
  85. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +0 -260
  86. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -227
  87. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +0 -260
  88. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -428
  89. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -258
  90. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +0 -294
  91. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
  92. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
  93. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +0 -334
  94. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +0 -19
  95. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
  96. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +0 -141
  97. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +0 -378
  98. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +0 -440
  99. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +0 -1400
  100. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +0 -339
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module OracleEnhanced
6
+ module OCIQuoting
7
+ def _type_cast(value)
8
+ case value
9
+ when ActiveModel::Type::Binary::Data
10
+ lob_value = value == "" ? " " : value
11
+ bind_type = OCI8::BLOB
12
+ ora_value = bind_type.new(@connection.raw_oci_connection, lob_value)
13
+ ora_value.size = 0 if value == ""
14
+ ora_value
15
+ when Type::OracleEnhanced::Text::Data
16
+ lob_value = value.to_s == "" ? " " : value.to_s
17
+ bind_type = OCI8::CLOB
18
+ ora_value = bind_type.new(@connection.raw_oci_connection, lob_value)
19
+ ora_value.size = 0 if value.to_s == ""
20
+ ora_value
21
+ when Type::OracleEnhanced::NationalCharacterText::Data
22
+ lob_value = value.to_s == "" ? " " : value.to_s
23
+ bind_type = OCI8::NCLOB
24
+ ora_value = bind_type.new(@connection.raw_oci_connection, lob_value)
25
+ ora_value.size = 0 if value.to_s == ""
26
+ ora_value
27
+ else
28
+ super
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ module ActiveRecord
37
+ module ConnectionAdapters
38
+ module OracleEnhanced
39
+ module Quoting
40
+ prepend OCIQuoting
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+
5
+ module ActiveRecord #:nodoc:
6
+ # Custom create, update, delete methods functionality.
7
+ #
8
+ # Example:
9
+ #
10
+ # class Employee < ActiveRecord::Base
11
+ # include ActiveRecord::OracleEnhancedProcedures
12
+ #
13
+ # set_create_method do
14
+ # plsql.employees_pkg.create_employee(
15
+ # :p_first_name => first_name,
16
+ # :p_last_name => last_name,
17
+ # :p_employee_id => nil
18
+ # )[:p_employee_id]
19
+ # end
20
+ #
21
+ # set_update_method do
22
+ # plsql.employees_pkg.update_employee(
23
+ # :p_employee_id => id,
24
+ # :p_first_name => first_name,
25
+ # :p_last_name => last_name
26
+ # )
27
+ # end
28
+ #
29
+ # set_delete_method do
30
+ # plsql.employees_pkg.delete_employee(
31
+ # :p_employee_id => id
32
+ # )
33
+ # end
34
+ # end
35
+ #
36
+ module OracleEnhancedProcedures #:nodoc:
37
+ module ClassMethods
38
+ # Specify custom create method which should be used instead of Rails generated INSERT statement.
39
+ # Provided block should return ID of new record.
40
+ # Example:
41
+ # set_create_method do
42
+ # plsql.employees_pkg.create_employee(
43
+ # :p_first_name => first_name,
44
+ # :p_last_name => last_name,
45
+ # :p_employee_id => nil
46
+ # )[:p_employee_id]
47
+ # end
48
+ def set_create_method(&block)
49
+ self.custom_create_method = block
50
+ end
51
+
52
+ # Specify custom update method which should be used instead of Rails generated UPDATE statement.
53
+ # Example:
54
+ # set_update_method do
55
+ # plsql.employees_pkg.update_employee(
56
+ # :p_employee_id => id,
57
+ # :p_first_name => first_name,
58
+ # :p_last_name => last_name
59
+ # )
60
+ # end
61
+ def set_update_method(&block)
62
+ self.custom_update_method = block
63
+ end
64
+
65
+ # Specify custom delete method which should be used instead of Rails generated DELETE statement.
66
+ # Example:
67
+ # set_delete_method do
68
+ # plsql.employees_pkg.delete_employee(
69
+ # :p_employee_id => id
70
+ # )
71
+ # end
72
+ def set_delete_method(&block)
73
+ self.custom_delete_method = block
74
+ end
75
+ end
76
+
77
+ def self.included(base)
78
+ base.class_eval do
79
+ extend ClassMethods
80
+ class_attribute :custom_create_method
81
+ class_attribute :custom_update_method
82
+ class_attribute :custom_delete_method
83
+ end
84
+ end
85
+
86
+ def destroy #:nodoc:
87
+ # check if class has custom delete method
88
+ if self.class.custom_delete_method
89
+ # wrap destroy in transaction
90
+ with_transaction_returning_status do
91
+ # run before/after callbacks defined in model
92
+ run_callbacks(:destroy) { destroy_using_custom_method }
93
+ end
94
+ else
95
+ super
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ # Creates a record with custom create method
102
+ # and returns its id.
103
+ def _create_record
104
+ # check if class has custom create method
105
+ if self.class.custom_create_method
106
+ # run before/after callbacks defined in model
107
+ run_callbacks(:create) do
108
+ # timestamp
109
+ if self.record_timestamps
110
+ current_time = current_time_from_proper_timezone
111
+
112
+ all_timestamp_attributes_in_model.each do |column|
113
+ if respond_to?(column) && respond_to?("#{column}=") && self.send(column).nil?
114
+ write_attribute(column.to_s, current_time)
115
+ end
116
+ end
117
+ end
118
+ # run
119
+ create_using_custom_method
120
+ end
121
+ else
122
+ super
123
+ end
124
+ end
125
+
126
+ def create_using_custom_method
127
+ log_custom_method("custom create method", "#{self.class.name} Create") do
128
+ self.id = instance_eval(&self.class.custom_create_method)
129
+ end
130
+ @new_record = false
131
+ # Starting from ActiveRecord 3.0.3 @persisted is used instead of @new_record
132
+ @persisted = true
133
+ id
134
+ end
135
+
136
+ # Updates the associated record with custom update method
137
+ # Returns the number of affected rows.
138
+ def _update_record(attribute_names = @attributes.keys)
139
+ # check if class has custom update method
140
+ if self.class.custom_update_method
141
+ # run before/after callbacks defined in model
142
+ run_callbacks(:update) do
143
+ # timestamp
144
+ if should_record_timestamps?
145
+ current_time = current_time_from_proper_timezone
146
+
147
+ timestamp_attributes_for_update_in_model.each do |column|
148
+ column = column.to_s
149
+ next if will_save_change_to_attribute?(column)
150
+ write_attribute(column, current_time)
151
+ end
152
+ end
153
+ # update just dirty attributes
154
+ if partial_writes?
155
+ # Serialized attributes should always be written in case they've been
156
+ # changed in place.
157
+ update_using_custom_method(changed | (attributes.keys & self.class.columns.select { |column| column.is_a?(Type::Serialized) }))
158
+ else
159
+ update_using_custom_method(attributes.keys)
160
+ end
161
+ end
162
+ else
163
+ super
164
+ end
165
+ end
166
+
167
+ def update_using_custom_method(attribute_names)
168
+ return 0 if attribute_names.empty?
169
+ log_custom_method("custom update method with #{self.class.primary_key}=#{self.id}", "#{self.class.name} Update") do
170
+ instance_eval(&self.class.custom_update_method)
171
+ end
172
+ 1
173
+ end
174
+
175
+ # Deletes the record in the database with custom delete method
176
+ # and freezes this instance to reflect that no changes should
177
+ # be made (since they can't be persisted).
178
+ def destroy_using_custom_method
179
+ unless new_record? || @destroyed
180
+ log_custom_method("custom delete method with #{self.class.primary_key}=#{self.id}", "#{self.class.name} Destroy") do
181
+ instance_eval(&self.class.custom_delete_method)
182
+ end
183
+ end
184
+
185
+ @destroyed = true
186
+ freeze
187
+ end
188
+
189
+ def log_custom_method(*args)
190
+ self.class.connection.send(:log, *args) { yield }
191
+ end
192
+
193
+ alias_method :update_record, :_update_record if private_method_defined?(:_update_record)
194
+ alias_method :create_record, :_create_record if private_method_defined?(:_create_record)
195
+ end
196
+ end
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module OracleEnhanced
6
+ module Quoting
7
+ # QUOTING ==================================================
8
+ #
9
+ # see: abstract/quoting.rb
10
+
11
+ def quote_column_name(name) #:nodoc:
12
+ name = name.to_s
13
+ @quoted_column_names[name] ||= begin
14
+ # if only valid lowercase column characters in name
15
+ if name =~ /\A[a-z][a-z_0-9\$#]*\Z/
16
+ "\"#{name.upcase}\""
17
+ else
18
+ # remove double quotes which cannot be used inside quoted identifier
19
+ "\"#{name.gsub('"', '')}\""
20
+ end
21
+ end
22
+ end
23
+
24
+ # This method is used in add_index to identify either column name (which is quoted)
25
+ # or function based index (in which case function expression is not quoted)
26
+ def quote_column_name_or_expression(name) #:nodoc:
27
+ name = name.to_s
28
+ case name
29
+ # if only valid lowercase column characters in name
30
+ when /^[a-z][a-z_0-9\$#]*$/
31
+ "\"#{name.upcase}\""
32
+ when /^[a-z][a-z_0-9\$#\-]*$/i
33
+ "\"#{name}\""
34
+ # if other characters present then assume that it is expression
35
+ # which should not be quoted
36
+ else
37
+ name
38
+ end
39
+ end
40
+
41
+ # Used only for quoting database links as the naming rules for links
42
+ # differ from the rules for column names. Specifically, link names may
43
+ # include periods.
44
+ def quote_database_link(name)
45
+ case name
46
+ when NONQUOTED_DATABASE_LINK
47
+ %Q("#{name.upcase}")
48
+ else
49
+ name
50
+ end
51
+ end
52
+
53
+ # Names must be from 1 to 30 bytes long with these exceptions:
54
+ # * Names of databases are limited to 8 bytes.
55
+ # * Names of database links can be as long as 128 bytes.
56
+ #
57
+ # Nonquoted identifiers cannot be Oracle Database reserved words
58
+ #
59
+ # Nonquoted identifiers must begin with an alphabetic character from
60
+ # your database character set
61
+ #
62
+ # Nonquoted identifiers can contain only alphanumeric characters from
63
+ # your database character set and the underscore (_), dollar sign ($),
64
+ # and pound sign (#). Database links can also contain periods (.) and
65
+ # "at" signs (@). Oracle strongly discourages you from using $ and # in
66
+ # nonquoted identifiers.
67
+ NONQUOTED_OBJECT_NAME = /[[:alpha:]][\w$#]{0,29}/
68
+ NONQUOTED_DATABASE_LINK = /[[:alpha:]][\w$#\.@]{0,127}/
69
+ VALID_TABLE_NAME = /\A(?:#{NONQUOTED_OBJECT_NAME}\.)?#{NONQUOTED_OBJECT_NAME}(?:@#{NONQUOTED_DATABASE_LINK})?\Z/
70
+
71
+ # unescaped table name should start with letter and
72
+ # contain letters, digits, _, $ or #
73
+ # can be prefixed with schema name
74
+ # CamelCase table names should be quoted
75
+ def self.valid_table_name?(name) #:nodoc:
76
+ object_name = name.to_s
77
+ !!(object_name =~ VALID_TABLE_NAME && !mixed_case?(object_name))
78
+ end
79
+
80
+ def self.mixed_case?(name)
81
+ object_name = name.include?(".") ? name.split(".").second : name
82
+ !!(object_name =~ /[A-Z]/ && object_name =~ /[a-z]/)
83
+ end
84
+
85
+ def quote_table_name(name) #:nodoc:
86
+ name, link = name.to_s.split("@")
87
+ @quoted_table_names[name] ||= [name.split(".").map { |n| quote_column_name(n) }.join("."), quote_database_link(link)].compact.join("@")
88
+ end
89
+
90
+ def quote_string(s) #:nodoc:
91
+ s.gsub(/'/, "''")
92
+ end
93
+
94
+ def _quote(value) #:nodoc:
95
+ case value
96
+ when Type::OracleEnhanced::NationalCharacterString::Data then
97
+ "N".dup << "'#{quote_string(value.to_s)}'"
98
+ when ActiveModel::Type::Binary::Data then
99
+ "empty_blob()"
100
+ when Type::OracleEnhanced::Text::Data then
101
+ "empty_clob()"
102
+ when Type::OracleEnhanced::NationalCharacterText::Data then
103
+ "empty_nclob()"
104
+ else
105
+ super
106
+ end
107
+ end
108
+
109
+ def quoted_true #:nodoc:
110
+ return "'Y'" if emulate_booleans_from_strings
111
+ "1".freeze
112
+ end
113
+
114
+ def unquoted_true #:nodoc:
115
+ return "Y" if emulate_booleans_from_strings
116
+ "1".freeze
117
+ end
118
+
119
+ def quoted_false #:nodoc:
120
+ return "'N'" if emulate_booleans_from_strings
121
+ "0".freeze
122
+ end
123
+
124
+ def unquoted_false #:nodoc:
125
+ return "N" if emulate_booleans_from_strings
126
+ "0".freeze
127
+ end
128
+
129
+ def _type_cast(value)
130
+ case value
131
+ when Type::OracleEnhanced::TimestampTz::Data, Type::OracleEnhanced::TimestampLtz::Data
132
+ if value.acts_like?(:time)
133
+ zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
134
+ value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
135
+ else
136
+ value
137
+ end
138
+ when Type::OracleEnhanced::NationalCharacterString::Data
139
+ value.to_s
140
+ else
141
+ super
142
+ end
143
+ end
144
+
145
+ private
146
+
147
+ def oracle_downcase(column_name)
148
+ return nil if column_name.nil?
149
+ column_name =~ /[a-z]/ ? column_name : column_name.downcase
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ # if MRI or YARV
157
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
158
+ require "active_record/connection_adapters/oracle_enhanced/oci_quoting"
159
+ # if JRuby
160
+ elsif RUBY_ENGINE == "jruby"
161
+ require "active_record/connection_adapters/oracle_enhanced/jdbc_quoting"
162
+ else
163
+ raise "Unsupported Ruby engine #{RUBY_ENGINE}"
164
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module OracleEnhanced
6
+ class SchemaCreation < AbstractAdapter::SchemaCreation
7
+ private
8
+
9
+ def visit_ColumnDefinition(o)
10
+ if [:blob, :clob, :nclob].include?(sql_type = type_to_sql(o.type, o.options).downcase.to_sym)
11
+ if (tablespace = default_tablespace_for(sql_type))
12
+ @lob_tablespaces ||= {}
13
+ @lob_tablespaces[o.name] = tablespace
14
+ end
15
+ end
16
+ super
17
+ end
18
+
19
+ def visit_TableDefinition(o)
20
+ create_sql = "CREATE#{' GLOBAL TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} ".dup
21
+ statements = o.columns.map { |c| accept c }
22
+ statements << accept(o.primary_keys) if o.primary_keys
23
+
24
+ if supports_foreign_keys_in_create?
25
+ statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
26
+ end
27
+
28
+ create_sql << "(#{statements.join(', ')})" if statements.present?
29
+
30
+ unless o.temporary
31
+ @lob_tablespaces.each do |lob_column, tablespace|
32
+ create_sql << " LOB (#{quote_column_name(lob_column)}) STORE AS (TABLESPACE #{tablespace}) \n"
33
+ end if defined?(@lob_tablespaces)
34
+ create_sql << " ORGANIZATION #{o.organization}" if o.organization
35
+ if (tablespace = o.tablespace || default_tablespace_for(:table))
36
+ create_sql << " TABLESPACE #{tablespace}"
37
+ end
38
+ end
39
+ add_table_options!(create_sql, table_options(o))
40
+ create_sql << " AS #{to_sql(o.as)}" if o.as
41
+ create_sql
42
+ end
43
+
44
+ def default_tablespace_for(type)
45
+ OracleEnhancedAdapter.default_tablespaces[type]
46
+ end
47
+
48
+ def add_column_options!(sql, options)
49
+ type = options[:type] || ((column = options[:column]) && column.type)
50
+ type = type && type.to_sym
51
+ # handle case of defaults for CLOB/NCLOB columns, which would otherwise get "quoted" incorrectly
52
+ if options_include_default?(options)
53
+ if type == :text
54
+ sql << " DEFAULT #{@conn.quote(options[:default])}"
55
+ elsif type == :ntext
56
+ sql << " DEFAULT #{@conn.quote(options[:default])}"
57
+ else
58
+ sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}"
59
+ end
60
+ end
61
+ # must explicitly add NULL or NOT NULL to allow change_column to work on migrations
62
+ if options[:null] == false
63
+ sql << " NOT NULL"
64
+ elsif options[:null] == true
65
+ sql << " NULL" unless type == :primary_key
66
+ end
67
+ # add AS expression for virtual columns
68
+ if options[:as].present?
69
+ sql << " AS (#{options[:as]})"
70
+ end
71
+ if options[:primary_key] == true
72
+ sql << " PRIMARY KEY"
73
+ end
74
+ end
75
+
76
+ def action_sql(action, dependency)
77
+ if action == "UPDATE"
78
+ raise ArgumentError, <<-MSG.strip_heredoc
79
+ '#{action}' is not supported by Oracle
80
+ MSG
81
+ end
82
+ case dependency
83
+ when :nullify then "ON #{action} SET NULL"
84
+ when :cascade then "ON #{action} CASCADE"
85
+ else
86
+ raise ArgumentError, <<-MSG.strip_heredoc
87
+ '#{dependency}' is not supported for #{action}
88
+ Supported values are: :nullify, :cascade
89
+ MSG
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end