activerecord-oracle_enhanced-adapter 1.1.8 → 1.1.9

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