activerecord-oracle_enhanced-adapter 1.5.5 → 1.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b1f1f3ee668e111001b017dd37db4d5e70bb315f
4
- data.tar.gz: 10e4fdff8ab461b4e48ac248e8a61ccaa4fd1870
3
+ metadata.gz: bf76a19860e42ac1474f054e8382f4f24ff8da03
4
+ data.tar.gz: 2f9b7008612855e77c716dc8aabbab07ec33f77a
5
5
  SHA512:
6
- metadata.gz: 58dddb4992f8ae81c79ee379d0c26a0dcfe869df5e052e1892679a9f03ba440b623fe7b6b2d6c4a85e589bc80989b47e1285d8ad9139e19a64e249872701d566
7
- data.tar.gz: d42acd789d7733e82e7e70d8c81c453e9dbd0a3a3dc0b196901ed9552ad09580540559ee5dbb0ec30102ef83d389b313ba932bfe22dc5c7ef0cefda1347ff1db
6
+ metadata.gz: ed5674fe99c4187285e6190faf54e3694da5ec8ea40aa945c375a895cf6c726559e7a04cc1209acdc3c8cf11f3d6408ed2f817e1cfe84537b5c54b9e2603a750
7
+ data.tar.gz: f7fabceab51daaff7562882012f538fd7dc977bf5f294f7350b41f2ec08aaa002db5844bdda9f7324cad2fcab4344f15eb69c584828b3b58146d7223b479d589
data/History.md CHANGED
@@ -1,3 +1,28 @@
1
+ ## 1.5.6 / 2015-03-30
2
+
3
+ * Enhancements
4
+ * Support Rails 4.1.10 [#530]
5
+ * Remove warning message when JDK 8 is used [#525]
6
+ * Support RAW column types [#471]
7
+ * Properly quote database links [#556]
8
+ * Grant create view privilege to db user [#528]
9
+ * Read SYSTEM password from ENV ORACLE_SYSTEM_PASSWORD optionally [#529]
10
+ * Show original error message when loading ruby-oci8 library fails [#532]
11
+ * Update README that `OracleEnhancedProcedures` is not auto loaded [#474]
12
+ * Fix legacy schema support syntax [#507]
13
+ * Peform all unit test when tested with Oracle 12c [#465]
14
+ * Add `:if_exists` option to `drop_table` [#541]
15
+ * Extract OracleEnhancedDatabaseStatements [#449]
16
+ * Removed self.visitor_for(pool) method [#501]
17
+
18
+ * Bug Fix
19
+ * Fix serialized readonly lobs [#515]
20
+ * Do not dump schema information during structure dump [#558]
21
+ * Structure dump generates correct create or replace synonym [#453]
22
+ * Procedures and functions are created correctly by removing semi-colon [#456]
23
+ * Show support matrix of Java and JDBC Driver only when java_version >= '1.8' [#455]
24
+ * Update Gemfile dependencies so specs can run [#472]
25
+
1
26
  ## 1.5.5 / 2014-05-23
2
27
 
3
28
  * Enhancements
data/README.md CHANGED
@@ -179,11 +179,11 @@ If you want to put Oracle enhanced adapter on top of existing schema tables then
179
179
 
180
180
  class Employee < ActiveRecord::Base
181
181
  # specify schema and table name
182
- self.table_name "hr.hr_employees"
182
+ self.table_name = "hr.hr_employees"
183
183
  # specify primary key name
184
- self.primary_key "employee_id"
184
+ self.primary_key = "employee_id"
185
185
  # specify sequence name
186
- self.sequence_name "hr.hr_employee_s"
186
+ self.sequence_name = "hr.hr_employee_s"
187
187
  # set which DATE columns should be converted to Ruby Date
188
188
  set_date_columns :hired_on, :birth_date_on
189
189
  # set which DATE columns should be converted to Ruby Time
@@ -223,9 +223,10 @@ You can also access remote tables over database link using
223
223
 
224
224
  ### Custom create, update and delete methods
225
225
 
226
- If you have legacy schema and you are not allowed to do direct INSERTs, UPDATEs and DELETEs in legacy schema tables and need to use existing PL/SQL procedures for create, updated, delete operations then you should add `ruby-plsql` gem to your application and then define custom create, update and delete methods, see example:
226
+ If you have legacy schema and you are not allowed to do direct INSERTs, UPDATEs and DELETEs in legacy schema tables and need to use existing PL/SQL procedures for create, updated, delete operations then you should add `ruby-plsql` gem to your application, include `ActiveRecord::OracleEnhancedProcedures` in your model and then define custom create, update and delete methods, see example:
227
227
 
228
228
  class Employee < ActiveRecord::Base
229
+ include ActiveRecord::OracleEnhancedProcedures
229
230
  # when defining create method then return ID of new record that will be assigned to id attribute of new object
230
231
  set_create_method do
231
232
  plsql.employees_pkg.create_employee(
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.5
1
+ 1.5.6
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{activerecord-oracle_enhanced-adapter}
8
- s.version = "1.5.5"
8
+ s.version = "1.5.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.license = 'MIT'
12
12
  s.authors = [%q{Raimonds Simanovskis}]
13
- s.date = %q{2014-05-23}
13
+ s.date = %q{2015-03-30}
14
14
  s.description = %q{Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases.
15
15
  This adapter is superset of original ActiveRecord Oracle adapter.
16
16
  }
@@ -35,6 +35,7 @@ This adapter is superset of original ActiveRecord Oracle adapter.
35
35
  "lib/active_record/connection_adapters/oracle_enhanced_connection.rb",
36
36
  "lib/active_record/connection_adapters/oracle_enhanced_context_index.rb",
37
37
  "lib/active_record/connection_adapters/oracle_enhanced_cpk.rb",
38
+ "lib/active_record/connection_adapters/oracle_enhanced_database_statements.rb",
38
39
  "lib/active_record/connection_adapters/oracle_enhanced_dirty.rb",
39
40
  "lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb",
40
41
  "lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb",
@@ -53,7 +53,7 @@ module ActiveRecord
53
53
  end
54
54
 
55
55
  # Specify which table columns should be typecasted to Date (without time), e.g.:
56
- #
56
+ #
57
57
  # set_date_columns :created_on, :updated_on
58
58
  def self.set_date_columns(*args)
59
59
  connection.set_type_for_columns(table_name,:date,*args)
@@ -120,19 +120,18 @@ module ActiveRecord
120
120
  private
121
121
 
122
122
  def enhanced_write_lobs
123
- if self.class.connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
123
+ if self.class.connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
124
124
  !(
125
125
  (self.class.custom_create_method || self.class.custom_create_method) ||
126
126
  (self.class.custom_update_method || self.class.custom_update_method)
127
127
  )
128
- self.class.connection.write_lobs(self.class.table_name, self.class, attributes, @changed_lob_columns || self.class.lob_columns)
128
+ self.class.connection.write_lobs(self.class.table_name, self.class, attributes, @changed_lob_columns)
129
129
  end
130
130
  end
131
131
 
132
132
  def record_changed_lobs
133
133
  @changed_lob_columns = self.class.lob_columns.select do |col|
134
- self.class.serialized_attributes.keys.include?(col.name) ||
135
- (self.send(:"#{col.name}_changed?") && !self.class.readonly_attributes.to_a.include?(col.name))
134
+ (self.class.serialized_attributes.keys.include?(col.name) || self.send(:"#{col.name}_changed?")) && !self.class.readonly_attributes.to_a.include?(col.name)
136
135
  end
137
136
  end
138
137
  end
@@ -402,10 +401,6 @@ module ActiveRecord
402
401
  end
403
402
  end
404
403
 
405
- def self.visitor_for(pool) # :nodoc:
406
- Arel::Visitors::Oracle.new(pool)
407
- end
408
-
409
404
  ADAPTER_NAME = 'OracleEnhanced'.freeze
410
405
 
411
406
  def adapter_name #:nodoc:
@@ -505,7 +500,7 @@ module ActiveRecord
505
500
  index_name_length
506
501
  end
507
502
 
508
- # the maximum length of an index name
503
+ # the maximum length of an index name
509
504
  # supported by this database
510
505
  def index_name_length
511
506
  IDENTIFIER_MAX_LENGTH
@@ -557,6 +552,18 @@ module ActiveRecord
557
552
  end
558
553
  end
559
554
 
555
+ # Used only for quoting database links as the naming rules for links
556
+ # differ from the rules for column names. Specifically, link names may
557
+ # include periods.
558
+ def quote_database_link(name)
559
+ case name
560
+ when NONQUOTED_DATABASE_LINK
561
+ %Q("#{name.upcase}")
562
+ else
563
+ name
564
+ end
565
+ end
566
+
560
567
  # Names must be from 1 to 30 bytes long with these exceptions:
561
568
  # * Names of databases are limited to 8 bytes.
562
569
  # * Names of database links can be as long as 128 bytes.
@@ -585,8 +592,8 @@ module ActiveRecord
585
592
  end
586
593
 
587
594
  def quote_table_name(name) #:nodoc:
588
- name = name.to_s
589
- @quoted_table_names[name] ||= name.split('.').map{|n| n.split('@').map{|m| quote_column_name(m)}.join('@')}.join('.')
595
+ name, link = name.to_s.split('@')
596
+ @quoted_table_names[name] ||= [name.split('.').map{|n| quote_column_name(n)}.join('.'), quote_database_link(link)].compact.join('@')
590
597
  end
591
598
 
592
599
  def quote_string(s) #:nodoc:
@@ -728,187 +735,6 @@ module ActiveRecord
728
735
  @connection.logoff rescue nil
729
736
  end
730
737
 
731
- # DATABASE STATEMENTS ======================================
732
- #
733
- # see: abstract/database_statements.rb
734
-
735
- # Executes a SQL statement
736
- def execute(sql, name = nil)
737
- log(sql, name) { @connection.exec(sql) }
738
- end
739
-
740
- def substitute_at(column, index)
741
- Arel::Nodes::BindParam.new (":a#{index + 1}")
742
- end
743
-
744
- def clear_cache!
745
- @statements.clear
746
- end
747
-
748
- def exec_query(sql, name = 'SQL', binds = [])
749
- type_casted_binds = binds.map { |col, val|
750
- [col, type_cast(val, col)]
751
- }
752
- log(sql, name, type_casted_binds) do
753
- cursor = nil
754
- cached = false
755
- if without_prepared_statement?(binds)
756
- cursor = @connection.prepare(sql)
757
- else
758
- unless @statements.key? sql
759
- @statements[sql] = @connection.prepare(sql)
760
- end
761
-
762
- cursor = @statements[sql]
763
-
764
- binds.each_with_index do |bind, i|
765
- col, val = bind
766
- cursor.bind_param(i + 1, type_cast(val, col), col)
767
- end
768
-
769
- cached = true
770
- end
771
-
772
- cursor.exec
773
-
774
- if name == 'EXPLAIN' and sql =~ /^EXPLAIN/
775
- res = true
776
- else
777
- columns = cursor.get_col_names.map do |col_name|
778
- @connection.oracle_downcase(col_name)
779
- end
780
- rows = []
781
- fetch_options = {:get_lob_value => (name != 'Writable Large Object')}
782
- while row = cursor.fetch(fetch_options)
783
- rows << row
784
- end
785
- res = ActiveRecord::Result.new(columns, rows)
786
- end
787
-
788
- cursor.close unless cached
789
- res
790
- end
791
- end
792
-
793
- def supports_statement_cache?
794
- true
795
- end
796
-
797
- def supports_explain?
798
- true
799
- end
800
-
801
- def explain(arel, binds = [])
802
- sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
803
- return if sql =~ /FROM all_/
804
- if ORACLE_ENHANCED_CONNECTION == :jdbc
805
- exec_query(sql, 'EXPLAIN', binds)
806
- else
807
- exec_query(sql, 'EXPLAIN')
808
- end
809
- select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", 'EXPLAIN').join("\n")
810
- end
811
-
812
- # Returns an array of arrays containing the field values.
813
- # Order is the same as that returned by #columns.
814
- def select_rows(sql, name = nil, binds = [])
815
- exec_query(sql, name, binds).rows
816
- end
817
-
818
- # Executes an INSERT statement and returns the new record's ID
819
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
820
- # if primary key value is already prefetched from sequence
821
- # or if there is no primary key
822
- if id_value || pk.nil?
823
- execute(sql, name)
824
- return id_value
825
- end
826
-
827
- sql_with_returning = sql + @connection.returning_clause(quote_column_name(pk))
828
- log(sql, name) do
829
- @connection.exec_with_returning(sql_with_returning)
830
- end
831
- end
832
- protected :insert_sql
833
-
834
- # New method in ActiveRecord 3.1
835
- # Will add RETURNING clause in case of trigger generated primary keys
836
- def sql_for_insert(sql, pk, id_value, sequence_name, binds)
837
- unless id_value || pk.nil? || (defined?(CompositePrimaryKeys) && pk.kind_of?(CompositePrimaryKeys::CompositeKeys))
838
- sql = "#{sql} RETURNING #{quote_column_name(pk)} INTO :returning_id"
839
- returning_id_col = OracleEnhancedColumn.new("returning_id", nil, "number", true, "dual", :integer, true, true)
840
- (binds = binds.dup) << [returning_id_col, nil]
841
- end
842
- [sql, binds]
843
- end
844
-
845
- # New method in ActiveRecord 3.1
846
- def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
847
- type_casted_binds = binds.map { |col, val|
848
- [col, type_cast(val, col)]
849
- }
850
- log(sql, name, type_casted_binds) do
851
- returning_id_col = returning_id_index = nil
852
- if without_prepared_statement?(binds)
853
- cursor = @connection.prepare(sql)
854
- else
855
- unless @statements.key? (sql)
856
- @statements[sql] = @connection.prepare(sql)
857
- end
858
-
859
- cursor = @statements[sql]
860
-
861
- binds.each_with_index do |bind, i|
862
- col, val = bind
863
- if col.returning_id?
864
- returning_id_col = [col]
865
- returning_id_index = i + 1
866
- cursor.bind_returning_param(returning_id_index, Integer)
867
- else
868
- cursor.bind_param(i + 1, type_cast(val, col), col)
869
- end
870
- end
871
- end
872
-
873
- cursor.exec_update
874
-
875
- rows = []
876
- if returning_id_index
877
- returning_id = cursor.get_returning_param(returning_id_index, Integer)
878
- rows << [returning_id]
879
- end
880
- ActiveRecord::Result.new(returning_id_col || [], rows)
881
- end
882
- end
883
-
884
- # New method in ActiveRecord 3.1
885
- def exec_update(sql, name, binds)
886
- log(sql, name, binds) do
887
- cached = false
888
- if without_prepared_statement?(binds)
889
- cursor = @connection.prepare(sql)
890
- else
891
- cursor = if @statements.key?(sql)
892
- @statements[sql]
893
- else
894
- @statements[sql] = @connection.prepare(sql)
895
- end
896
-
897
- binds.each_with_index do |bind, i|
898
- col, val = bind
899
- cursor.bind_param(i + 1, type_cast(val, col), col)
900
- end
901
- cached = true
902
- end
903
-
904
- res = cursor.exec_update
905
- cursor.close unless cached
906
- res
907
- end
908
- end
909
-
910
- alias :exec_delete :exec_update
911
-
912
738
  # use in set_sequence_name to avoid fetching primary key value from sequence
913
739
  AUTOGENERATED_SEQUENCE_NAME = 'autogenerated'.freeze
914
740
 
@@ -922,49 +748,6 @@ module ActiveRecord
922
748
  @connection.select_value("SELECT #{quote_table_name(sequence_name)}.NEXTVAL FROM dual")
923
749
  end
924
750
 
925
- def begin_db_transaction #:nodoc:
926
- @connection.autocommit = false
927
- end
928
-
929
- def transaction_isolation_levels
930
- # Oracle database supports `READ COMMITTED` and `SERIALIZABLE`
931
- # No read uncommitted nor repeatable read supppoted
932
- # http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10005.htm#SQLRF55422
933
- {
934
- read_committed: "READ COMMITTED",
935
- serializable: "SERIALIZABLE"
936
- }
937
- end
938
-
939
- def begin_isolated_db_transaction(isolation)
940
- begin_db_transaction
941
- execute "SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}"
942
- end
943
-
944
- def commit_db_transaction #:nodoc:
945
- @connection.commit
946
- ensure
947
- @connection.autocommit = true
948
- end
949
-
950
- def rollback_db_transaction #:nodoc:
951
- @connection.rollback
952
- ensure
953
- @connection.autocommit = true
954
- end
955
-
956
- def create_savepoint(name = current_savepoint_name) #:nodoc:
957
- execute("SAVEPOINT #{current_savepoint_name}")
958
- end
959
-
960
- def rollback_to_savepoint(name = current_savepoint_name) #:nodoc:
961
- execute("ROLLBACK TO #{current_savepoint_name}")
962
- end
963
-
964
- def release_savepoint(name = current_savepoint_name) #:nodoc:
965
- # there is no RELEASE SAVEPOINT statement in Oracle
966
- end
967
-
968
751
  @@do_not_prefetch_primary_key = {}
969
752
 
970
753
  # Returns true for Oracle adapter (since Oracle requires primary key
@@ -987,12 +770,6 @@ module ActiveRecord
987
770
  @@do_not_prefetch_primary_key = {}
988
771
  end
989
772
 
990
- # Returns default sequence name for table.
991
- # Will take all or first 26 characters of table name and append _seq suffix
992
- def default_sequence_name(table_name, primary_key = nil)
993
- table_name.to_s.gsub /(^|\.)([\w$-]{1,#{sequence_name_length-4}})([\w$-]*)$/, '\1\2_seq'
994
- end
995
-
996
773
  def reset_pk_sequence!(table_name, primary_key = nil, sequence_name = nil) #:nodoc:
997
774
  return nil unless table_exists?(table_name)
998
775
  unless primary_key and sequence_name
@@ -1017,27 +794,11 @@ module ActiveRecord
1017
794
  select NVL(max(#{quote_column_name(primary_key)}),0) + 1 from #{quote_table_name(table_name)}
1018
795
  ", new_start_value)
1019
796
 
1020
- execute ("DROP SEQUENCE #{quote_table_name(sequence_name)}")
797
+ execute ("DROP SEQUENCE #{quote_table_name(sequence_name)}")
1021
798
  execute ("CREATE SEQUENCE #{quote_table_name(sequence_name)} START WITH #{new_start_value}")
1022
799
  end
1023
800
  end
1024
801
 
1025
- # Inserts the given fixture into the table. Overridden to properly handle lobs.
1026
- def insert_fixture(fixture, table_name) #:nodoc:
1027
- super
1028
-
1029
- if ActiveRecord::Base.pluralize_table_names
1030
- klass = table_name.to_s.singularize.camelize
1031
- else
1032
- klass = table_name.to_s.camelize
1033
- end
1034
-
1035
- klass = klass.constantize rescue nil
1036
- if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base)
1037
- write_lobs(table_name, klass, fixture, klass.lob_columns)
1038
- end
1039
- end
1040
-
1041
802
  # Writes LOB values from attributes for specified columns
1042
803
  def write_lobs(table_name, klass, attributes, columns) #:nodoc:
1043
804
  # is class with composite primary key>
@@ -1400,16 +1161,16 @@ module ActiveRecord
1400
1161
  c = c.to_sql unless c.is_a?(String)
1401
1162
  # remove any ASC/DESC modifiers
1402
1163
  c.gsub(/\s+(ASC|DESC)\s*?/i, '')
1403
- }.reject(&:blank?).map.with_index { |c,i|
1404
- "FIRST_VALUE(#{c}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__"
1164
+ }.reject(&:blank?).map.with_index { |c,i|
1165
+ "FIRST_VALUE(#{c}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__"
1405
1166
  }
1406
1167
  [super].concat(order_columns).join(', ')
1407
1168
  end
1408
- end
1169
+ end
1409
1170
 
1410
1171
  def columns_for_distinct(columns, orders) #:nodoc:
1411
- # construct a valid columns name for DISTINCT clause,
1412
- # ie. one that includes the ORDER BY columns, using FIRST_VALUE such that
1172
+ # construct a valid columns name for DISTINCT clause,
1173
+ # ie. one that includes the ORDER BY columns, using FIRST_VALUE such that
1413
1174
  # the inclusion of these columns doesn't invalidate the DISTINCT
1414
1175
  #
1415
1176
  # It does not construct DISTINCT clause. Just return column names for distinct.
@@ -1459,16 +1220,6 @@ module ActiveRecord
1459
1220
 
1460
1221
  private
1461
1222
 
1462
- def select(sql, name = nil, binds = [])
1463
- if ActiveRecord.const_defined?(:Result)
1464
- exec_query(sql, name, binds)
1465
- else
1466
- log(sql, name) do
1467
- @connection.select(sql, name, false)
1468
- end
1469
- end
1470
- end
1471
-
1472
1223
  def oracle_downcase(column_name)
1473
1224
  @connection.oracle_downcase(column_name)
1474
1225
  end
@@ -1570,3 +1321,6 @@ require 'active_record/connection_adapters/oracle_enhanced_column_dumper'
1570
1321
 
1571
1322
  # Moved SchemaCreation class
1572
1323
  require 'active_record/connection_adapters/oracle_enhanced_schema_creation'
1324
+
1325
+ # Moved DatabaseStetements
1326
+ require 'active_record/connection_adapters/oracle_enhanced_database_statements'