pmacs-activerecord-oracle_enhanced-adapter 1.5.5.1 → 1.5.6.1

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: 55fb63832be212bdf12fc8a8e9ef24b385d2dd71
4
- data.tar.gz: bd81a44bc261832f358a0eb1ef297911f73110a1
3
+ metadata.gz: dfd9dfc216e8abfe2b49a29ca26b706c96c25b4c
4
+ data.tar.gz: ae40965f3d27b5bcd55759c008eedb1de94c6734
5
5
  SHA512:
6
- metadata.gz: 8122b64d689f4abf8143f73fa141da3f7f461b3d31f56845f3d1a5916bc9c1db7b0d7f6a9b0a3aedc0af4deea95f1d08bf81b8814da356d37810f03438608ce1
7
- data.tar.gz: 79beb44492fd15f7e122e91623fcb09c6bfef9b33038a92ef9599dd9b2b4783db375d1b2b0d6d11868ad64b48a1de35e3bd6d11133546a747c0a41a3de80d763
6
+ metadata.gz: bc8d709b07ced146b51b9ece9f2b0207403c4f3dd5159c063c87bac3ff572a08e0e893450a8742108aaffa63ff69d2850b325f753ea3628a9b198da63f63494c
7
+ data.tar.gz: 6d047603b5a70ae34e37ecc414746c2a083dc63688499fea2428f67be854b544baaeac096283bdc836cdd8857db60d8d0666d078fe779a8f0384898d92952cc5
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
@@ -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>
@@ -1405,16 +1166,16 @@ module ActiveRecord
1405
1166
  c = c.to_sql unless c.is_a?(String)
1406
1167
  # remove any ASC/DESC modifiers
1407
1168
  c.gsub(/\s+(ASC|DESC)\s*?/i, '')
1408
- }.reject(&:blank?).map.with_index { |c,i|
1409
- "FIRST_VALUE(#{c}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__"
1169
+ }.reject(&:blank?).map.with_index { |c,i|
1170
+ "FIRST_VALUE(#{c}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__"
1410
1171
  }
1411
1172
  [super].concat(order_columns).join(', ')
1412
1173
  end
1413
- end
1174
+ end
1414
1175
 
1415
1176
  def columns_for_distinct(columns, orders) #:nodoc:
1416
- # construct a valid columns name for DISTINCT clause,
1417
- # ie. one that includes the ORDER BY columns, using FIRST_VALUE such that
1177
+ # construct a valid columns name for DISTINCT clause,
1178
+ # ie. one that includes the ORDER BY columns, using FIRST_VALUE such that
1418
1179
  # the inclusion of these columns doesn't invalidate the DISTINCT
1419
1180
  #
1420
1181
  # It does not construct DISTINCT clause. Just return column names for distinct.
@@ -1464,16 +1225,6 @@ module ActiveRecord
1464
1225
 
1465
1226
  private
1466
1227
 
1467
- def select(sql, name = nil, binds = [])
1468
- if ActiveRecord.const_defined?(:Result)
1469
- exec_query(sql, name, binds)
1470
- else
1471
- log(sql, name) do
1472
- @connection.select(sql, name, false)
1473
- end
1474
- end
1475
- end
1476
-
1477
1228
  def oracle_downcase(column_name)
1478
1229
  @connection.oracle_downcase(column_name)
1479
1230
  end
@@ -1575,3 +1326,6 @@ require 'active_record/connection_adapters/oracle_enhanced_column_dumper'
1575
1326
 
1576
1327
  # Moved SchemaCreation class
1577
1328
  require 'active_record/connection_adapters/oracle_enhanced_schema_creation'
1329
+
1330
+ # Moved DatabaseStetements
1331
+ require 'active_record/connection_adapters/oracle_enhanced_database_statements'