activerecord-oracle_enhanced-adapter 1.5.5 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
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'