activerecord-oracle_enhanced-adapter 1.1.8 → 1.1.9

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ == 1.1.9 2009-01-02
2
+
3
+ * Enhancements
4
+ * Added support for table and column comments in migrations
5
+ * Added support for specifying sequence start values
6
+ * Added :privilege option (e.g. :SYSDBA) to ActiveRecord::Base.establish_connection
7
+ * Bug fixes:
8
+ * Do not mark empty decimals, strings and texts (stored as NULL in database) as changed when reassigning them (starting from Rails 2.1)
9
+ * Create booleans as VARCHAR2(1) columns if emulate_booleans_from_strings is true
10
+
1
11
  == 1.1.8 2008-10-10
2
12
 
3
13
  * Bug fixes:
data/README.txt CHANGED
@@ -7,78 +7,19 @@
7
7
  Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases
8
8
  from Rails which are extracted from current real projects' monkey patches of original Oracle adapter.
9
9
 
10
- See http://blog.rayapps.com/category/oracle-enhanced for more information.
10
+ See http://github.com/rsim/oracle-enhanced/wikis for more information.
11
11
 
12
- Look ar RSpec tests under spec directory for usage examples.
12
+ For questions and feature discussion please use http://groups.google.com/group/oracle-enhanced
13
13
 
14
- == FEATURES/PROBLEMS:
14
+ Blog posts about oracle-enahnced can be found at http://blog.rayapps.com/category/oracle-enhanced
15
15
 
16
-
17
- == SYNOPSIS:
18
-
19
- In Rails config/database.yml file use oracle_enhanced as adapter name.
20
-
21
- Create config/initializers/oracle_advanced.rb file in your Rails application and put configuration options there.
22
- The following configuration options are available:
23
-
24
- * set to true if columns with DATE in their name should be emulated as Date (and not as Time which is default)
25
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
26
-
27
- * set to true if columns with ID at the end of column name should be emulated as Fixnum (and not as BigDecimal which is default)
28
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
29
-
30
- * set to true if CHAR(1), VARCHAR2(1) columns or VARCHAR2 columns with FLAG or YN at the end of their name
31
- should be emulated as booleans (and do not use NUMBER(1) as type for booleans which is default)
32
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
33
-
34
- * specify other date and time formats that should be used when assigning string values to :date and :datetime columns, e.g.:
35
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = "%d.%m.%Y"
36
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = "%d.%m.%Y %H:%M:%S"
37
-
38
- The following model class methods are available:
39
- * specify which table columns should be ignored by ActiveRecord
40
- ignore_table_columns :column1, :column2, :column3
41
-
42
- * specify which table columns should be with :date type (without time) or with :datetime type (with date and time) - this could be used
43
- if emulation by column names is not working because of different naming conventions
44
- set_date_columns :started_on, :finished_on
45
- set_datetime_columns :start_date_and_time, :end_date_and_time
46
-
47
- * specify which table columns should be with :boolean type - this should be used together with boolean emulation from strings if
48
- there are other boolean columns with different naming convention
49
- set_boolean_columns :some_boolean_column
50
-
51
- * specify custom create, update and delete methods which should be used instead of Rails generated INSERT, UPDATE and DELETE statements
52
- # should return ID of new record
53
- set_create_method do
54
- plsql.employees_pkg.create_employee(
55
- :p_first_name => first_name,
56
- :p_last_name => last_name,
57
- :p_employee_id => nil
58
- )[:p_employee_id]
59
- end
60
- set_update_method do
61
- plsql.employees_pkg.update_employee(
62
- :p_employee_id => id,
63
- :p_first_name => first_name,
64
- :p_last_name => last_name
65
- )
66
- end
67
- set_delete_method do
68
- plsql.employees_pkg.delete_employee(
69
- :p_employee_id => id
70
- )
71
- end
72
-
73
- Oracle enhanced adapter is also compatible with composite_primary_keys gem.
74
-
75
- See History.txt for other enhancements to original Oracle adapter.
16
+ Bugs and enhancement requests can be reported at http://rsim.lighthouseapp.com/projects/11468-oracle-enhanced
76
17
 
77
18
  == REQUIREMENTS:
78
19
 
79
- * Works with ActiveRecord version 2.0 and 2.1 (which is included in Rails 2.0 and 2.1)
20
+ * Works (has been tested) with ActiveRecord version 2.0, 2.1 and 2.2 (these are the same as Rails versions)
80
21
  * Requires ruby-oci8 library to connect to Oracle
81
- * Requires ruby-plsql gem to support custom create, update and delete methods
22
+ * Requires ruby-plsql gem to support custom create, update and delete methods (but can be used without ruby-plsql if this functionality is not needed)
82
23
 
83
24
  == INSTALL:
84
25
 
@@ -88,7 +29,7 @@ See History.txt for other enhancements to original Oracle adapter.
88
29
 
89
30
  (The MIT License)
90
31
 
91
- Copyright (c) 2008 Graham Jenkins, Michael Schoen, Raimonds Simanovskis
32
+ Copyright (c) 2009 Graham Jenkins, Michael Schoen, Raimonds Simanovskis
92
33
 
93
34
  Permission is hereby granted, free of charge, to any person obtaining
94
35
  a copy of this software and associated documentation files (the
@@ -107,6 +107,10 @@ begin
107
107
  alias_method :add_order!, :add_order_with_lobs!
108
108
  end
109
109
 
110
+ # RSI: get table comment from schema definition
111
+ def self.table_comment
112
+ self.connection.table_comment(self.table_name)
113
+ end
110
114
  end
111
115
 
112
116
 
@@ -147,6 +151,12 @@ begin
147
151
  return string.to_time if string.is_a?(Date) && !OracleEnhancedAdapter.emulate_dates
148
152
  super
149
153
  end
154
+
155
+ # RSI: get column comment from schema definition
156
+ # will work only if using default ActiveRecord connection
157
+ def comment
158
+ ActiveRecord::Base.connection.column_comment(@table_name, name)
159
+ end
150
160
 
151
161
  private
152
162
  def simplified_type(field_type)
@@ -308,7 +318,9 @@ begin
308
318
  :time => { :name => "DATE" },
309
319
  :date => { :name => "DATE" },
310
320
  :binary => { :name => "BLOB" },
311
- :boolean => { :name => "NUMBER", :limit => 1 }
321
+ # RSI: if emulate_booleans_from_strings then store booleans in VARCHAR2
322
+ :boolean => emulate_booleans_from_strings ?
323
+ { :name => "VARCHAR2", :limit => 1 } : { :name => "NUMBER", :limit => 1 }
312
324
  }
313
325
  end
314
326
 
@@ -633,12 +645,16 @@ begin
633
645
  end
634
646
  end
635
647
 
648
+ # RSI: default sequence start with value
649
+ @@default_sequence_start_value = 10000
650
+ cattr_accessor :default_sequence_start_value
651
+
636
652
  def create_table(name, options = {}, &block) #:nodoc:
637
653
  create_sequence = options[:id] != false
638
- if create_sequence
639
- super(name, options, &block)
640
- else
641
- super(name, options) do |t|
654
+ column_comments = {}
655
+ super(name, options) do |t|
656
+ # store that primary key was defined in create_table block
657
+ unless create_sequence
642
658
  class <<t
643
659
  attr_accessor :create_sequence
644
660
  def primary_key(*args)
@@ -646,12 +662,34 @@ begin
646
662
  super(*args)
647
663
  end
648
664
  end
649
- result = block.call(t)
650
- create_sequence = t.create_sequence
651
665
  end
666
+
667
+ # store column comments
668
+ class <<t
669
+ attr_accessor :column_comments
670
+ def column(name, type, options = {})
671
+ if options[:comment]
672
+ self.column_comments ||= {}
673
+ self.column_comments[name] = options[:comment]
674
+ end
675
+ super(name, type, options)
676
+ end
677
+ end
678
+
679
+ result = block.call(t)
680
+ create_sequence = create_sequence || t.create_sequence
681
+ column_comments = t.column_comments if t.column_comments
652
682
  end
683
+
653
684
  seq_name = options[:sequence_name] || "#{name}_seq"
654
- execute "CREATE SEQUENCE #{seq_name} START WITH 10000" if create_sequence
685
+ seq_start_value = options[:sequence_start_value] || default_sequence_start_value
686
+ execute "CREATE SEQUENCE #{seq_name} START WITH #{seq_start_value}" if create_sequence
687
+
688
+ add_table_comment name, options[:comment]
689
+ column_comments.each do |column_name, comment|
690
+ add_comment name, column_name, comment
691
+ end
692
+
655
693
  end
656
694
 
657
695
  def rename_table(name, new_name) #:nodoc:
@@ -687,6 +725,36 @@ begin
687
725
  execute "ALTER TABLE #{table_name} DROP COLUMN #{quote_column_name(column_name)}"
688
726
  end
689
727
 
728
+ # RSI: table and column comments
729
+ def add_comment(table_name, column_name, comment)
730
+ return if comment.blank?
731
+ execute "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{column_name} IS '#{comment}'"
732
+ end
733
+
734
+ def add_table_comment(table_name, comment)
735
+ return if comment.blank?
736
+ execute "COMMENT ON TABLE #{quote_table_name(table_name)} IS '#{comment}'"
737
+ end
738
+
739
+ def table_comment(table_name)
740
+ (owner, table_name) = @connection.describe(table_name)
741
+ select_value <<-SQL
742
+ SELECT comments FROM all_tab_comments
743
+ WHERE owner = '#{owner}'
744
+ AND table_name = '#{table_name}'
745
+ SQL
746
+ end
747
+
748
+ def column_comment(table_name, column_name)
749
+ (owner, table_name) = @connection.describe(table_name)
750
+ select_value <<-SQL
751
+ SELECT comments FROM all_col_comments
752
+ WHERE owner = '#{owner}'
753
+ AND table_name = '#{table_name}'
754
+ AND column_name = '#{column_name.upcase}'
755
+ SQL
756
+ end
757
+
690
758
  # Find a table's primary key and sequence.
691
759
  # *Note*: Only primary key is implemented - sequence will be nil.
692
760
  def pk_and_sequence_for(table_name)
@@ -916,8 +984,8 @@ begin
916
984
  # The OracleConnectionFactory factors out the code necessary to connect and
917
985
  # configure an Oracle/OCI connection.
918
986
  class OracleEnhancedConnectionFactory #:nodoc:
919
- def new_connection(username, password, database, async, prefetch_rows, cursor_sharing)
920
- conn = OCI8.new username, password, database
987
+ def new_connection(username, password, database, async, prefetch_rows, cursor_sharing, privilege)
988
+ conn = OCI8.new username, password, database, privilege
921
989
  conn.exec %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'}
922
990
  conn.exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'} rescue nil
923
991
  conn.autocommit = true
@@ -953,7 +1021,8 @@ begin
953
1021
  @prefetch_rows = config[:prefetch_rows] || 100
954
1022
  @cursor_sharing = config[:cursor_sharing] || 'similar'
955
1023
  @factory = factory
956
- @connection = @factory.new_connection @username, @password, @database, @async, @prefetch_rows, @cursor_sharing
1024
+ @privilege = config[:privilege]
1025
+ @connection = @factory.new_connection @username, @password, @database, @async, @prefetch_rows, @cursor_sharing, @privilege
957
1026
  super @connection
958
1027
  end
959
1028
 
@@ -972,7 +1041,7 @@ begin
972
1041
  def reset!
973
1042
  logoff rescue nil
974
1043
  begin
975
- @connection = @factory.new_connection @username, @password, @database, @async, @prefetch_rows, @cursor_sharing
1044
+ @connection = @factory.new_connection @username, @password, @database, @async, @prefetch_rows, @cursor_sharing, @privilege
976
1045
  __setobj__ @connection
977
1046
  @active = true
978
1047
  rescue
@@ -1048,3 +1117,6 @@ end
1048
1117
 
1049
1118
  # RSI: load additional methods for composite_primary_keys support
1050
1119
  require 'active_record/connection_adapters/oracle_enhanced_cpk'
1120
+
1121
+ # RSI: load patch for dirty tracking methods
1122
+ require 'active_record/connection_adapters/oracle_enhanced_dirty'
@@ -0,0 +1,39 @@
1
+ module ActiveRecord #:nodoc:
2
+ module ConnectionAdapters #:nodoc:
3
+ module OracleEnhancedDirty #:nodoc:
4
+
5
+ module InstanceMethods
6
+ private
7
+
8
+ def field_changed?(attr, old, value)
9
+ if column = column_for_attribute(attr)
10
+ # RSI: added also :decimal type
11
+ if (column.type == :integer || column.type == :decimal) && column.null && (old.nil? || old == 0)
12
+ # For nullable integer columns, NULL gets stored in database for blank (i.e. '') values.
13
+ # Hence we don't record it as a change if the value changes from nil to ''.
14
+ # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll
15
+ # be typecast back to 0 (''.to_i => 0)
16
+ value = nil if value.blank?
17
+ # RSI: Oracle stores empty string '' or empty text (CLOB) as NULL
18
+ # therefore need to convert empty string value to nil if old value is nil
19
+ elsif (column.type == :string || column.type == :text) && column.null && old.nil?
20
+ value = nil if value == ''
21
+ else
22
+ value = column.type_cast(value)
23
+ end
24
+ end
25
+
26
+ old != value
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+
35
+ if ActiveRecord::Base.instance_methods.include?('changed?')
36
+ ActiveRecord::Base.class_eval do
37
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedDirty::InstanceMethods
38
+ end
39
+ end
@@ -3,7 +3,7 @@ module ActiveRecord #:nodoc:
3
3
  module OracleEnhancedVersion #:nodoc:
4
4
  MAJOR = 1
5
5
  MINOR = 1
6
- TINY = 8
6
+ TINY = 9
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY].join('.')
9
9
  end
@@ -2,14 +2,21 @@ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
2
 
3
3
  describe "OracleEnhancedAdapter establish connection" do
4
4
 
5
- before(:all) do
5
+ it "should connect to database" do
6
6
  ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
7
7
  :database => "xe",
8
8
  :username => "hr",
9
9
  :password => "hr")
10
+ ActiveRecord::Base.connection.should_not be_nil
11
+ ActiveRecord::Base.connection.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
10
12
  end
11
-
12
- it "should connect to database" do
13
+
14
+ it "should connect to database as SYSDBA" do
15
+ ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
16
+ :database => "xe",
17
+ :username => "sys",
18
+ :password => "manager",
19
+ :privilege => :SYSDBA)
13
20
  ActiveRecord::Base.connection.should_not be_nil
14
21
  ActiveRecord::Base.connection.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
15
22
  end
@@ -158,432 +165,6 @@ describe "OracleEnhancedAdapter database session store" do
158
165
 
159
166
  end
160
167
 
161
- describe "OracleEnhancedAdapter date type detection based on column names" do
162
- before(:all) do
163
- ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
164
- :database => "xe",
165
- :username => "hr",
166
- :password => "hr")
167
- @conn = ActiveRecord::Base.connection
168
- @conn.execute <<-SQL
169
- CREATE TABLE test_employees (
170
- employee_id NUMBER(6,0),
171
- first_name VARCHAR2(20),
172
- last_name VARCHAR2(25),
173
- email VARCHAR2(25),
174
- phone_number VARCHAR2(20),
175
- hire_date DATE,
176
- job_id NUMBER(6,0),
177
- salary NUMBER(8,2),
178
- commission_pct NUMBER(2,2),
179
- manager_id NUMBER(6,0),
180
- department_id NUMBER(4,0),
181
- created_at DATE,
182
- updated_at DATE
183
- )
184
- SQL
185
- @conn.execute <<-SQL
186
- CREATE SEQUENCE test_employees_seq MINVALUE 1
187
- INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
188
- SQL
189
- end
190
-
191
- after(:all) do
192
- @conn.execute "DROP TABLE test_employees"
193
- @conn.execute "DROP SEQUENCE test_employees_seq"
194
- end
195
-
196
- it "should set DATE column type as datetime if emulate_dates_by_column_name is false" do
197
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
198
- columns = @conn.columns('test_employees')
199
- column = columns.detect{|c| c.name == "hire_date"}
200
- column.type.should == :datetime
201
- end
202
-
203
- it "should set DATE column type as date if column name contains '_date_' and emulate_dates_by_column_name is true" do
204
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
205
- columns = @conn.columns('test_employees')
206
- column = columns.detect{|c| c.name == "hire_date"}
207
- column.type.should == :date
208
- end
209
-
210
- it "should set DATE column type as datetime if column name does not contain '_date_' and emulate_dates_by_column_name is true" do
211
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
212
- columns = @conn.columns('test_employees')
213
- column = columns.detect{|c| c.name == "created_at"}
214
- column.type.should == :datetime
215
- end
216
-
217
- it "should set DATE column type as datetime if column name contains 'date' as part of other word and emulate_dates_by_column_name is true" do
218
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
219
- columns = @conn.columns('test_employees')
220
- column = columns.detect{|c| c.name == "updated_at"}
221
- column.type.should == :datetime
222
- end
223
-
224
- it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
225
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
226
- columns = @conn.columns('test_employees')
227
- column = columns.detect{|c| c.name == "hire_date"}
228
- column.type_cast(Time.now).class.should == Time
229
- end
230
-
231
- it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
232
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
233
- columns = @conn.columns('test_employees')
234
- column = columns.detect{|c| c.name == "hire_date"}
235
- column.type_cast(Time.now).class.should == Date
236
- end
237
-
238
- describe "/ DATE values from ActiveRecord model" do
239
- before(:each) do
240
- ActiveRecord::Base.connection.clear_types_for_columns
241
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
242
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = false
243
- class TestEmployee < ActiveRecord::Base
244
- set_table_name "hr.test_employees"
245
- set_primary_key :employee_id
246
- end
247
- end
248
-
249
- def create_test_employee
250
- @today = Date.new(2008,8,19)
251
- @now = Time.local(2008,8,19,17,03,59)
252
- @employee = TestEmployee.create(
253
- :first_name => "First",
254
- :last_name => "Last",
255
- :hire_date => @today,
256
- :created_at => @now
257
- )
258
- @employee.reload
259
- end
260
-
261
- after(:each) do
262
- # @employee.destroy if @employee
263
- Object.send(:remove_const, "TestEmployee")
264
- end
265
-
266
- it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
267
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
268
- create_test_employee
269
- @employee.hire_date.class.should == Time
270
- end
271
-
272
- it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
273
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
274
- create_test_employee
275
- @employee.hire_date.class.should == Date
276
- end
277
-
278
- it "should return Time value from DATE column if column name does not contain 'date' and emulate_dates_by_column_name is true" do
279
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
280
- create_test_employee
281
- @employee.created_at.class.should == Time
282
- end
283
-
284
- it "should return Date value from DATE column if emulate_dates_by_column_name is false but column is defined as date" do
285
- class TestEmployee < ActiveRecord::Base
286
- set_date_columns :hire_date
287
- end
288
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
289
- create_test_employee
290
- @employee.hire_date.class.should == Date
291
- end
292
-
293
- it "should return Time value from DATE column if emulate_dates_by_column_name is true but column is defined as datetime" do
294
- class TestEmployee < ActiveRecord::Base
295
- set_datetime_columns :hire_date
296
- end
297
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
298
- create_test_employee
299
- @employee.hire_date.class.should == Time
300
- # change to current time with hours, minutes and seconds
301
- @employee.hire_date = @now
302
- @employee.save!
303
- @employee.reload
304
- @employee.hire_date.class.should == Time
305
- @employee.hire_date.should == @now
306
- end
307
-
308
- it "should guess Date or Time value if emulate_dates is true" do
309
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = true
310
- create_test_employee
311
- @employee.hire_date.class.should == Date
312
- @employee.created_at.class.should == Time
313
- end
314
-
315
- end
316
-
317
- end
318
-
319
- describe "OracleEnhancedAdapter integer type detection based on column names" do
320
- before(:all) do
321
- ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
322
- :database => "xe",
323
- :username => "hr",
324
- :password => "hr")
325
- @conn = ActiveRecord::Base.connection
326
- @conn.execute <<-SQL
327
- CREATE TABLE test2_employees (
328
- id NUMBER,
329
- first_name VARCHAR2(20),
330
- last_name VARCHAR2(25),
331
- email VARCHAR2(25),
332
- phone_number VARCHAR2(20),
333
- hire_date DATE,
334
- job_id NUMBER,
335
- salary NUMBER,
336
- commission_pct NUMBER(2,2),
337
- manager_id NUMBER(6),
338
- department_id NUMBER(4,0),
339
- created_at DATE
340
- )
341
- SQL
342
- @conn.execute <<-SQL
343
- CREATE SEQUENCE test2_employees_seq MINVALUE 1
344
- INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
345
- SQL
346
- end
347
-
348
- after(:all) do
349
- @conn.execute "DROP TABLE test2_employees"
350
- @conn.execute "DROP SEQUENCE test2_employees_seq"
351
- end
352
-
353
- it "should set NUMBER column type as decimal if emulate_integers_by_column_name is false" do
354
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
355
- columns = @conn.columns('test2_employees')
356
- column = columns.detect{|c| c.name == "job_id"}
357
- column.type.should == :decimal
358
- end
359
-
360
- it "should set NUMBER column type as integer if emulate_integers_by_column_name is true" do
361
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
362
- columns = @conn.columns('test2_employees')
363
- column = columns.detect{|c| c.name == "job_id"}
364
- column.type.should == :integer
365
- column = columns.detect{|c| c.name == "id"}
366
- column.type.should == :integer
367
- end
368
-
369
- it "should set NUMBER column type as decimal if column name does not contain 'id' and emulate_integers_by_column_name is true" do
370
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
371
- columns = @conn.columns('test2_employees')
372
- column = columns.detect{|c| c.name == "salary"}
373
- column.type.should == :decimal
374
- end
375
-
376
- it "should return BigDecimal value from NUMBER column if emulate_integers_by_column_name is false" do
377
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
378
- columns = @conn.columns('test2_employees')
379
- column = columns.detect{|c| c.name == "job_id"}
380
- column.type_cast(1.0).class.should == BigDecimal
381
- end
382
-
383
- it "should return Fixnum value from NUMBER column if column name contains 'id' and emulate_integers_by_column_name is true" do
384
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
385
- columns = @conn.columns('test2_employees')
386
- column = columns.detect{|c| c.name == "job_id"}
387
- column.type_cast(1.0).class.should == Fixnum
388
- end
389
-
390
- describe "/ NUMBER values from ActiveRecord model" do
391
- before(:each) do
392
- class Test2Employee < ActiveRecord::Base
393
- end
394
- end
395
-
396
- after(:each) do
397
- Object.send(:remove_const, "Test2Employee")
398
- end
399
-
400
- def create_employee2
401
- @employee2 = Test2Employee.create(
402
- :first_name => "First",
403
- :last_name => "Last",
404
- :job_id => 1,
405
- :salary => 1000
406
- )
407
- @employee2.reload
408
- end
409
-
410
- it "should return BigDecimal value from NUMBER column if emulate_integers_by_column_name is false" do
411
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
412
- create_employee2
413
- @employee2.job_id.class.should == BigDecimal
414
- end
415
-
416
- it "should return Fixnum value from NUMBER column if column name contains 'id' and emulate_integers_by_column_name is true" do
417
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
418
- create_employee2
419
- @employee2.job_id.class.should == Fixnum
420
- end
421
-
422
- it "should return BigDecimal value from NUMBER column if column name does not contain 'id' and emulate_integers_by_column_name is true" do
423
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
424
- create_employee2
425
- @employee2.salary.class.should == BigDecimal
426
- end
427
-
428
- end
429
-
430
- end
431
-
432
- describe "OracleEnhancedAdapter boolean type detection based on string column types and names" do
433
- before(:all) do
434
- ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
435
- :database => "xe",
436
- :username => "hr",
437
- :password => "hr")
438
- @conn = ActiveRecord::Base.connection
439
- @conn.execute <<-SQL
440
- CREATE TABLE test3_employees (
441
- id NUMBER,
442
- first_name VARCHAR2(20),
443
- last_name VARCHAR2(25),
444
- email VARCHAR2(25),
445
- phone_number VARCHAR2(20),
446
- hire_date DATE,
447
- job_id NUMBER,
448
- salary NUMBER,
449
- commission_pct NUMBER(2,2),
450
- manager_id NUMBER(6),
451
- department_id NUMBER(4,0),
452
- created_at DATE,
453
- has_email CHAR(1),
454
- has_phone VARCHAR2(1),
455
- active_flag VARCHAR2(2),
456
- manager_yn VARCHAR2(3),
457
- test_boolean VARCHAR2(3)
458
- )
459
- SQL
460
- @conn.execute <<-SQL
461
- CREATE SEQUENCE test3_employees_seq MINVALUE 1
462
- INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
463
- SQL
464
- end
465
-
466
- after(:all) do
467
- @conn.execute "DROP TABLE test3_employees"
468
- @conn.execute "DROP SEQUENCE test3_employees_seq"
469
- end
470
-
471
- it "should set CHAR/VARCHAR2 column type as string if emulate_booleans_from_strings is false" do
472
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
473
- columns = @conn.columns('test3_employees')
474
- %w(has_email has_phone active_flag manager_yn).each do |col|
475
- column = columns.detect{|c| c.name == col}
476
- column.type.should == :string
477
- end
478
- end
479
-
480
- it "should set CHAR/VARCHAR2 column type as boolean if emulate_booleans_from_strings is true" do
481
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
482
- columns = @conn.columns('test3_employees')
483
- %w(has_email has_phone active_flag manager_yn).each do |col|
484
- column = columns.detect{|c| c.name == col}
485
- column.type.should == :boolean
486
- end
487
- end
488
-
489
- it "should set VARCHAR2 column type as string if column name does not contain 'flag' or 'yn' and emulate_booleans_from_strings is true" do
490
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
491
- columns = @conn.columns('test3_employees')
492
- %w(phone_number email).each do |col|
493
- column = columns.detect{|c| c.name == col}
494
- column.type.should == :string
495
- end
496
- end
497
-
498
- it "should return string value from VARCHAR2 boolean column if emulate_booleans_from_strings is false" do
499
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
500
- columns = @conn.columns('test3_employees')
501
- %w(has_email has_phone active_flag manager_yn).each do |col|
502
- column = columns.detect{|c| c.name == col}
503
- column.type_cast("Y").class.should == String
504
- end
505
- end
506
-
507
- it "should return boolean value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
508
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
509
- columns = @conn.columns('test3_employees')
510
- %w(has_email has_phone active_flag manager_yn).each do |col|
511
- column = columns.detect{|c| c.name == col}
512
- column.type_cast("Y").class.should == TrueClass
513
- column.type_cast("N").class.should == FalseClass
514
- end
515
- end
516
-
517
- describe "/ VARCHAR2 boolean values from ActiveRecord model" do
518
- before(:each) do
519
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
520
- class Test3Employee < ActiveRecord::Base
521
- end
522
- end
523
-
524
- after(:each) do
525
- Object.send(:remove_const, "Test3Employee")
526
- end
527
-
528
- def create_employee3(params={})
529
- @employee3 = Test3Employee.create(
530
- {
531
- :first_name => "First",
532
- :last_name => "Last",
533
- :has_email => true,
534
- :has_phone => false,
535
- :active_flag => true,
536
- :manager_yn => false
537
- }.merge(params)
538
- )
539
- @employee3.reload
540
- end
541
-
542
- it "should return String value from VARCHAR2 boolean column if emulate_booleans_from_strings is false" do
543
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
544
- create_employee3
545
- %w(has_email has_phone active_flag manager_yn).each do |col|
546
- @employee3.send(col.to_sym).class.should == String
547
- end
548
- end
549
-
550
- it "should return boolean value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
551
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
552
- create_employee3
553
- %w(has_email active_flag).each do |col|
554
- @employee3.send(col.to_sym).class.should == TrueClass
555
- @employee3.send((col+"_before_type_cast").to_sym).should == "Y"
556
- end
557
- %w(has_phone manager_yn).each do |col|
558
- @employee3.send(col.to_sym).class.should == FalseClass
559
- @employee3.send((col+"_before_type_cast").to_sym).should == "N"
560
- end
561
- end
562
-
563
- it "should return string value from VARCHAR2 column if it is not boolean column and emulate_booleans_from_strings is true" do
564
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
565
- create_employee3
566
- @employee3.first_name.class.should == String
567
- end
568
-
569
- it "should return boolean value from VARCHAR2 boolean column if column specified in set_boolean_columns" do
570
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
571
- class Test3Employee < ActiveRecord::Base
572
- set_boolean_columns :test_boolean
573
- end
574
- create_employee3(:test_boolean => true)
575
- @employee3.test_boolean.class.should == TrueClass
576
- @employee3.test_boolean_before_type_cast.should == "Y"
577
- create_employee3(:test_boolean => false)
578
- @employee3.test_boolean.class.should == FalseClass
579
- @employee3.test_boolean_before_type_cast.should == "N"
580
- end
581
-
582
- end
583
-
584
- end
585
-
586
-
587
168
  describe "OracleEnhancedAdapter ignore specified table columns" do
588
169
  before(:all) do
589
170
  ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
@@ -647,453 +228,223 @@ describe "OracleEnhancedAdapter ignore specified table columns" do
647
228
 
648
229
  end
649
230
 
231
+ describe "OracleEnhancedAdapter table and sequence creation with non-default primary key" do
650
232
 
651
- describe "OracleEnhancedAdapter timestamp with timezone support" do
652
233
  before(:all) do
653
234
  ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
654
235
  :database => "xe",
655
236
  :username => "hr",
656
237
  :password => "hr")
657
- @conn = ActiveRecord::Base.connection
658
- @conn.execute <<-SQL
659
- CREATE TABLE test_employees (
660
- employee_id NUMBER(6,0),
661
- first_name VARCHAR2(20),
662
- last_name VARCHAR2(25),
663
- email VARCHAR2(25),
664
- phone_number VARCHAR2(20),
665
- hire_date DATE,
666
- job_id NUMBER(6,0),
667
- salary NUMBER(8,2),
668
- commission_pct NUMBER(2,2),
669
- manager_id NUMBER(6,0),
670
- department_id NUMBER(4,0),
671
- created_at TIMESTAMP,
672
- created_at_tz TIMESTAMP WITH TIME ZONE,
673
- created_at_ltz TIMESTAMP WITH LOCAL TIME ZONE
674
- )
675
- SQL
676
- @conn.execute <<-SQL
677
- CREATE SEQUENCE test_employees_seq MINVALUE 1
678
- INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
679
- SQL
680
- end
681
-
682
- after(:all) do
683
- @conn.execute "DROP TABLE test_employees"
684
- @conn.execute "DROP SEQUENCE test_employees_seq"
685
- end
686
-
687
- it "should set TIMESTAMP columns type as datetime" do
688
- columns = @conn.columns('test_employees')
689
- ts_columns = columns.select{|c| c.name =~ /created_at/}
690
- ts_columns.each {|c| c.type.should == :timestamp}
691
- end
692
-
693
- describe "/ TIMESTAMP WITH TIME ZONE values from ActiveRecord model" do
694
- before(:all) do
695
- class TestEmployee < ActiveRecord::Base
696
- set_primary_key :employee_id
238
+ ActiveRecord::Schema.define do
239
+ suppress_messages do
240
+ create_table :keyboards, :force => true, :id => false do |t|
241
+ t.primary_key :key_number
242
+ t.string :name
243
+ end
244
+ create_table :id_keyboards, :force => true do |t|
245
+ t.string :name
246
+ end
697
247
  end
698
248
  end
699
-
700
- after(:all) do
701
- Object.send(:remove_const, "TestEmployee")
249
+ class Keyboard < ActiveRecord::Base
250
+ set_primary_key :key_number
702
251
  end
703
-
704
- it "should return Time value from TIMESTAMP columns" do
705
- # currently fractional seconds are not retrieved from database
706
- @now = Time.local(2008,5,26,23,11,11,0)
707
- @employee = TestEmployee.create(
708
- :created_at => @now,
709
- :created_at_tz => @now,
710
- :created_at_ltz => @now
711
- )
712
- @employee.reload
713
- [:created_at, :created_at_tz, :created_at_ltz].each do |c|
714
- @employee.send(c).class.should == Time
715
- @employee.send(c).to_f.should == @now.to_f
716
- end
252
+ class IdKeyboard < ActiveRecord::Base
717
253
  end
718
-
719
- it "should return Time value without fractional seconds from TIMESTAMP columns" do
720
- # currently fractional seconds are not retrieved from database
721
- @now = Time.local(2008,5,26,23,11,11,10)
722
- @employee = TestEmployee.create(
723
- :created_at => @now,
724
- :created_at_tz => @now,
725
- :created_at_ltz => @now
726
- )
727
- @employee.reload
728
- [:created_at, :created_at_tz, :created_at_ltz].each do |c|
729
- @employee.send(c).class.should == Time
730
- @employee.send(c).to_f.should == @now.to_f.to_i.to_f # remove fractional seconds
254
+ end
255
+
256
+ after(:all) do
257
+ ActiveRecord::Schema.define do
258
+ suppress_messages do
259
+ drop_table :keyboards
260
+ drop_table :id_keyboards
731
261
  end
732
262
  end
733
-
263
+ Object.send(:remove_const, "Keyboard")
264
+ Object.send(:remove_const, "IdKeyboard")
265
+ end
266
+
267
+ it "should create sequence for non-default primary key" do
268
+ ActiveRecord::Base.connection.next_sequence_value(Keyboard.sequence_name).should_not be_nil
734
269
  end
735
270
 
271
+ it "should create sequence for default primary key" do
272
+ ActiveRecord::Base.connection.next_sequence_value(IdKeyboard.sequence_name).should_not be_nil
273
+ end
736
274
  end
737
275
 
276
+ describe "OracleEnhancedAdapter without composite_primary_keys" do
738
277
 
739
- describe "OracleEnhancedAdapter date and timestamp with different NLS date formats" do
740
278
  before(:all) do
741
279
  ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
742
280
  :database => "xe",
743
281
  :username => "hr",
744
282
  :password => "hr")
745
- @conn = ActiveRecord::Base.connection
746
- @conn.execute <<-SQL
747
- CREATE TABLE test_employees (
748
- employee_id NUMBER(6,0),
749
- first_name VARCHAR2(20),
750
- last_name VARCHAR2(25),
751
- email VARCHAR2(25),
752
- phone_number VARCHAR2(20),
753
- hire_date DATE,
754
- job_id NUMBER(6,0),
755
- salary NUMBER(8,2),
756
- commission_pct NUMBER(2,2),
757
- manager_id NUMBER(6,0),
758
- department_id NUMBER(4,0),
759
- created_at DATE,
760
- created_at_ts TIMESTAMP
761
- )
762
- SQL
763
- @conn.execute <<-SQL
764
- CREATE SEQUENCE test_employees_seq MINVALUE 1
765
- INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
766
- SQL
767
- # @conn.execute %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'}
768
- @conn.execute %q{alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS'}
769
- # @conn.execute %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'}
770
- @conn.execute %q{alter session set nls_timestamp_format = 'DD-MON-YYYY HH24:MI:SS'}
771
- end
772
-
773
- after(:all) do
774
- @conn.execute "DROP TABLE test_employees"
775
- @conn.execute "DROP SEQUENCE test_employees_seq"
776
- end
777
-
778
- before(:each) do
779
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = false
780
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
781
- class TestEmployee < ActiveRecord::Base
283
+ Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
284
+ class Employee < ActiveRecord::Base
782
285
  set_primary_key :employee_id
783
286
  end
784
- @today = Date.new(2008,6,28)
785
- @now = Time.local(2008,6,28,13,34,33)
786
287
  end
787
288
 
788
- after(:each) do
789
- Object.send(:remove_const, "TestEmployee")
790
- end
791
-
792
- def create_test_employee
793
- @employee = TestEmployee.create(
794
- :first_name => "First",
795
- :last_name => "Last",
796
- :hire_date => @today,
797
- :created_at => @now,
798
- :created_at_ts => @now
799
- )
800
- @employee.reload
801
- end
802
-
803
- it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
804
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
805
- create_test_employee
806
- @employee.hire_date.class.should == Time
807
- @employee.hire_date.should == @today.to_time
808
- end
809
-
810
- it "should return Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
811
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
812
- create_test_employee
813
- @employee.hire_date.class.should == Date
814
- @employee.hire_date.should == @today
815
- end
816
-
817
- it "should return Time value from DATE column if column name does not contain 'date' and emulate_dates_by_column_name is true" do
818
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
819
- create_test_employee
820
- @employee.created_at.class.should == Time
821
- @employee.created_at.should == @now
822
- end
823
-
824
- it "should return Time value from TIMESTAMP columns" do
825
- create_test_employee
826
- @employee.created_at_ts.class.should == Time
827
- @employee.created_at_ts.should == @now
828
- end
829
-
830
- it "should quote Date values with TO_DATE" do
831
- @conn.quote(@today).should == "TO_DATE('#{@today.year}-#{"%02d" % @today.month}-#{"%02d" % @today.day}','YYYY-MM-DD HH24:MI:SS')"
832
- end
833
-
834
- it "should quote Time values with TO_DATE" do
835
- @conn.quote(@now).should == "TO_DATE('#{@now.year}-#{"%02d" % @now.month}-#{"%02d" % @now.day} "+
836
- "#{"%02d" % @now.hour}:#{"%02d" % @now.min}:#{"%02d" % @now.sec}','YYYY-MM-DD HH24:MI:SS')"
289
+ it "should tell ActiveRecord that count distinct is supported" do
290
+ ActiveRecord::Base.connection.supports_count_distinct?.should be_true
837
291
  end
838
292
 
839
- it "should quote Time values with TO_TIMESTAMP" do
840
- @ts = Time.at(@now.to_f + 0.1)
841
- @conn.quote(@ts).should == "TO_TIMESTAMP('#{@ts.year}-#{"%02d" % @ts.month}-#{"%02d" % @ts.day} "+
842
- "#{"%02d" % @ts.hour}:#{"%02d" % @ts.min}:#{"%02d" % @ts.sec}.100000','YYYY-MM-DD HH24:MI:SS.FF6')"
293
+ it "should execute correct SQL COUNT DISTINCT statement" do
294
+ lambda { Employee.count(:employee_id, :distinct => true) }.should_not raise_error
843
295
  end
844
296
 
845
297
  end
846
298
 
847
- describe "OracleEnhancedAdapter assign string to :date and :datetime columns" do
299
+ describe "OracleEnhancedAdapter sequence creation parameters" do
300
+
848
301
  before(:all) do
849
302
  ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
850
303
  :database => "xe",
851
304
  :username => "hr",
852
305
  :password => "hr")
853
- @conn = ActiveRecord::Base.connection
854
- @conn.execute <<-SQL
855
- CREATE TABLE test_employees (
856
- employee_id NUMBER(6,0),
857
- first_name VARCHAR2(20),
858
- last_name VARCHAR2(25),
859
- hire_date DATE,
860
- last_login_at DATE,
861
- last_login_at_ts TIMESTAMP
862
- )
863
- SQL
864
- @conn.execute <<-SQL
865
- CREATE SEQUENCE test_employees_seq MINVALUE 1
866
- INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
867
- SQL
868
- class TestEmployee < ActiveRecord::Base
869
- set_primary_key :employee_id
306
+ end
307
+
308
+ def create_test_employees_table(sequence_start_value = nil)
309
+ ActiveRecord::Schema.define do
310
+ suppress_messages do
311
+ create_table :test_employees, sequence_start_value ? {:sequence_start_value => sequence_start_value} : {} do |t|
312
+ t.string :first_name
313
+ t.string :last_name
314
+ end
315
+ end
870
316
  end
871
317
  end
872
318
 
873
- after(:all) do
874
- Object.send(:remove_const, "TestEmployee")
875
- @conn.execute "DROP TABLE test_employees"
876
- @conn.execute "DROP SEQUENCE test_employees_seq"
319
+ def save_default_sequence_start_value
320
+ @saved_sequence_start_value = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value
321
+ end
322
+
323
+ def restore_default_sequence_start_value
324
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = @saved_sequence_start_value
877
325
  end
878
326
 
879
327
  before(:each) do
880
- @today = Date.new(2008,6,28)
881
- @today_iso = "2008-06-28"
882
- @today_nls = "28.06.2008"
883
- @nls_date_format = "%d.%m.%Y"
884
- @now = Time.local(2008,6,28,13,34,33)
885
- @now_iso = "2008-06-28 13:34:33"
886
- @now_nls = "28.06.2008 13:34:33"
887
- @nls_time_format = "%d.%m.%Y %H:%M:%S"
888
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
328
+ save_default_sequence_start_value
889
329
  end
890
-
891
- it "should assign ISO string to date column" do
892
- @employee = TestEmployee.create(
893
- :first_name => "First",
894
- :last_name => "Last",
895
- :hire_date => @today_iso
896
- )
897
- @employee.reload
898
- @employee.hire_date.should == @today
330
+ after(:each) do
331
+ restore_default_sequence_start_value
332
+ ActiveRecord::Schema.define do
333
+ suppress_messages do
334
+ drop_table :test_employees
335
+ end
336
+ end
337
+ Object.send(:remove_const, "TestEmployee")
899
338
  end
900
339
 
901
- it "should assign NLS string to date column" do
902
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
903
- @employee = TestEmployee.create(
904
- :first_name => "First",
905
- :last_name => "Last",
906
- :hire_date => @today_nls
907
- )
908
- @employee.reload
909
- @employee.hire_date.should == @today
910
- end
340
+ it "should use default sequence start value 10000" do
341
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value.should == 10000
911
342
 
912
- it "should assign ISO time string to date column" do
913
- @employee = TestEmployee.create(
914
- :first_name => "First",
915
- :last_name => "Last",
916
- :hire_date => @now_iso
917
- )
918
- @employee.reload
919
- @employee.hire_date.should == @today
920
- end
343
+ create_test_employees_table
344
+ class TestEmployee < ActiveRecord::Base; end
921
345
 
922
- it "should assign NLS time string to date column" do
923
- # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
924
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
925
- @employee = TestEmployee.create(
926
- :first_name => "First",
927
- :last_name => "Last",
928
- :hire_date => @now_nls
929
- )
930
- @employee.reload
931
- @employee.hire_date.should == @today
346
+ employee = TestEmployee.create!
347
+ employee.id.should == 10000
932
348
  end
933
349
 
934
- it "should assign ISO time string to datetime column" do
935
- @employee = TestEmployee.create(
936
- :first_name => "First",
937
- :last_name => "Last",
938
- :last_login_at => @now_iso
939
- )
940
- @employee.reload
941
- @employee.last_login_at.should == @now
942
- end
350
+ it "should use specified default sequence start value" do
351
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = 1
943
352
 
944
- it "should assign NLS time string to datetime column" do
945
- # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
946
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
947
- @employee = TestEmployee.create(
948
- :first_name => "First",
949
- :last_name => "Last",
950
- :last_login_at => @now_nls
951
- )
952
- @employee.reload
953
- @employee.last_login_at.should == @now
954
- end
955
-
956
- it "should assign ISO date string to datetime column" do
957
- @employee = TestEmployee.create(
958
- :first_name => "First",
959
- :last_name => "Last",
960
- :last_login_at => @today_iso
961
- )
962
- @employee.reload
963
- @employee.last_login_at.should == @today.to_time
964
- end
353
+ create_test_employees_table
354
+ class TestEmployee < ActiveRecord::Base; end
965
355
 
966
- it "should assign NLS date string to datetime column" do
967
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = @nls_date_format
968
- # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = @nls_time_format
969
- @employee = TestEmployee.create(
970
- :first_name => "First",
971
- :last_name => "Last",
972
- :last_login_at => @today_nls
973
- )
974
- @employee.reload
975
- @employee.last_login_at.should == @today.to_time
356
+ employee = TestEmployee.create!
357
+ employee.id.should == 1
976
358
  end
977
-
978
- end
979
359
 
980
- describe "OracleEnhancedAdapter handling of CLOB columns" do
981
- before(:all) do
982
- ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
983
- :database => "xe",
984
- :username => "hr",
985
- :password => "hr")
986
- @conn = ActiveRecord::Base.connection
987
- @conn.execute <<-SQL
988
- CREATE TABLE test_employees (
989
- employee_id NUMBER(6,0),
990
- first_name VARCHAR2(20),
991
- last_name VARCHAR2(25),
992
- comments CLOB
993
- )
994
- SQL
995
- @conn.execute <<-SQL
996
- CREATE SEQUENCE test_employees_seq MINVALUE 1
997
- INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
998
- SQL
999
- class TestEmployee < ActiveRecord::Base
1000
- set_primary_key :employee_id
1001
- end
1002
- end
1003
-
1004
- after(:all) do
1005
- Object.send(:remove_const, "TestEmployee")
1006
- @conn.execute "DROP TABLE test_employees"
1007
- @conn.execute "DROP SEQUENCE test_employees_seq"
1008
- end
360
+ it "should use sequence start value from table definition" do
361
+ create_test_employees_table(10)
362
+ class TestEmployee < ActiveRecord::Base; end
1009
363
 
1010
- before(:each) do
1011
- end
1012
-
1013
- it "should create record without CLOB data when attribute is serialized" do
1014
- TestEmployee.serialize :comments
1015
- @employee = TestEmployee.create!(
1016
- :first_name => "First",
1017
- :last_name => "Last"
1018
- )
1019
- @employee.should be_valid
364
+ employee = TestEmployee.create!
365
+ employee.id.should == 10
1020
366
  end
1021
367
 
1022
- it "should order by CLOB column" do
1023
- @employee = TestEmployee.create!(
1024
- :first_name => "First",
1025
- :last_name => "Last",
1026
- :comments => "comments"
1027
- )
1028
- TestEmployee.find(:all, :order => "comments ASC").should_not be_empty
1029
- TestEmployee.find(:all, :order => " comments ASC ").should_not be_empty
1030
- TestEmployee.find(:all, :order => "comments").should_not be_empty
1031
- TestEmployee.find(:all, :order => " comments ").should_not be_empty
1032
- TestEmployee.find(:all, :order => :comments).should_not be_empty
1033
- TestEmployee.find(:all, :order => " first_name DESC, last_name ASC ").should_not be_empty
368
+ it "should use sequence start value and other options from table definition" do
369
+ create_test_employees_table("100 NOCACHE INCREMENT BY 10")
370
+ class TestEmployee < ActiveRecord::Base; end
371
+
372
+ employee = TestEmployee.create!
373
+ employee.id.should == 100
374
+ employee = TestEmployee.create!
375
+ employee.id.should == 110
1034
376
  end
1035
-
377
+
1036
378
  end
1037
379
 
1038
- describe "OracleEnhancedAdapter table and sequence creation with non-default primary key" do
380
+ describe "OracleEnhancedAdapter table and column comments" do
381
+
1039
382
  before(:all) do
1040
383
  ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
1041
384
  :database => "xe",
1042
385
  :username => "hr",
1043
386
  :password => "hr")
387
+ @conn = ActiveRecord::Base.connection
388
+ end
389
+
390
+ def create_test_employees_table(table_comment=nil, column_comments={})
1044
391
  ActiveRecord::Schema.define do
1045
- create_table :keyboards, :force => true, :id => false do |t|
1046
- t.primary_key :key_number
1047
- t.string :name
1048
- end
1049
- create_table :id_keyboards, :force => true do |t|
1050
- t.string :name
392
+ suppress_messages do
393
+ create_table :test_employees, :comment => table_comment do |t|
394
+ t.string :first_name, :comment => column_comments[:first_name]
395
+ t.string :last_name, :comment => column_comments[:last_name]
396
+ end
1051
397
  end
1052
398
  end
1053
- class Keyboard < ActiveRecord::Base
1054
- set_primary_key :key_number
1055
- end
1056
- class IdKeyboard < ActiveRecord::Base
1057
- end
1058
399
  end
1059
-
1060
- after(:all) do
400
+
401
+ after(:each) do
1061
402
  ActiveRecord::Schema.define do
1062
- drop_table :keyboards
1063
- drop_table :id_keyboards
403
+ suppress_messages do
404
+ drop_table :test_employees
405
+ end
1064
406
  end
1065
- Object.send(:remove_const, "Keyboard")
1066
- Object.send(:remove_const, "IdKeyboard")
1067
- end
1068
-
1069
- it "should create sequence for non-default primary key" do
1070
- ActiveRecord::Base.connection.next_sequence_value(Keyboard.sequence_name).should_not be_nil
407
+ Object.send(:remove_const, "TestEmployee")
408
+ ActiveRecord::Base.table_name_prefix = nil
1071
409
  end
1072
410
 
1073
- it "should create sequence for default primary key" do
1074
- ActiveRecord::Base.connection.next_sequence_value(IdKeyboard.sequence_name).should_not be_nil
411
+ it "should create table with table comment" do
412
+ table_comment = "Test Employees"
413
+ create_test_employees_table(table_comment)
414
+ class TestEmployee < ActiveRecord::Base; end
415
+
416
+ @conn.table_comment("test_employees").should == table_comment
417
+ TestEmployee.table_comment.should == table_comment
1075
418
  end
1076
- end
1077
419
 
1078
- describe "OracleEnhancedAdapter without composite_primary_keys" do
1079
-
1080
- before(:all) do
1081
- ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced",
1082
- :database => "xe",
1083
- :username => "hr",
1084
- :password => "hr")
1085
- Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
1086
- class Employee < ActiveRecord::Base
1087
- set_primary_key :employee_id
420
+ it "should create table with columns comment" do
421
+ column_comments = {:first_name => "Given Name", :last_name => "Surname"}
422
+ create_test_employees_table(nil, column_comments)
423
+ class TestEmployee < ActiveRecord::Base; end
424
+
425
+ [:first_name, :last_name].each do |attr|
426
+ @conn.column_comment("test_employees", attr.to_s).should == column_comments[attr]
427
+ end
428
+ [:first_name, :last_name].each do |attr|
429
+ TestEmployee.columns_hash[attr.to_s].comment.should == column_comments[attr]
1088
430
  end
1089
431
  end
1090
432
 
1091
- it "should tell ActiveRecord that count distinct is supported" do
1092
- ActiveRecord::Base.connection.supports_count_distinct?.should be_true
1093
- end
1094
-
1095
- it "should execute correct SQL COUNT DISTINCT statement" do
1096
- lambda { Employee.count(:employee_id, :distinct => true) }.should_not raise_error
433
+ it "should create table with table and columns comment and custom table name prefix" do
434
+ ActiveRecord::Base.table_name_prefix = "xxx_"
435
+ table_comment = "Test Employees"
436
+ column_comments = {:first_name => "Given Name", :last_name => "Surname"}
437
+ create_test_employees_table(table_comment, column_comments)
438
+ class TestEmployee < ActiveRecord::Base; end
439
+
440
+ @conn.table_comment(TestEmployee.table_name).should == table_comment
441
+ TestEmployee.table_comment.should == table_comment
442
+ [:first_name, :last_name].each do |attr|
443
+ @conn.column_comment(TestEmployee.table_name, attr.to_s).should == column_comments[attr]
444
+ end
445
+ [:first_name, :last_name].each do |attr|
446
+ TestEmployee.columns_hash[attr.to_s].comment.should == column_comments[attr]
447
+ end
1097
448
  end
1098
449
 
1099
450
  end