1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
# frozen-string-literal: true
Sequel::JDBC.load_driver('Java::oracle.jdbc.driver.OracleDriver')
require_relative '../shared/oracle'
require_relative 'transactions'
module Sequel
module JDBC
Sequel.synchronize do
DATABASE_SETUP[:oracle] = proc do |db|
db.extend(Sequel::JDBC::Oracle::DatabaseMethods)
db.dataset_class = Sequel::JDBC::Oracle::Dataset
Java::oracle.jdbc.driver.OracleDriver
end
end
module Oracle
JAVA_BIG_DECIMAL_CONSTRUCTOR = java.math.BigDecimal.java_class.constructor(Java::long).method(:new_instance)
ORACLE_DECIMAL = Object.new
def ORACLE_DECIMAL.call(r, i)
if v = r.getBigDecimal(i)
i = v.long_value
if v == JAVA_BIG_DECIMAL_CONSTRUCTOR.call(i)
i
else
::Kernel::BigDecimal(v.to_string)
end
end
end
ORACLE_CLOB = Object.new
def ORACLE_CLOB.call(r, i)
return unless clob = r.getClob(i)
str = clob.getSubString(1, clob.length)
clob.freeTemporary if clob.isTemporary
str
end
module DatabaseMethods
include Sequel::Oracle::DatabaseMethods
include Sequel::JDBC::Transactions
def self.extended(db)
db.instance_exec do
@autosequence = opts[:autosequence]
@primary_key_sequences = {}
end
end
private
# Oracle exception handling with SQLState is less accurate than with regexps.
def database_exception_use_sqlstates?
false
end
def disconnect_error?(exception, opts)
super || exception.message =~ /\AClosed Connection/
end
# Default the fetch size for statements to 100, similar to the oci8-based oracle adapter.
def default_fetch_size
100
end
def last_insert_id(conn, opts)
unless sequence = opts[:sequence]
if t = opts[:table]
sequence = sequence_for_table(t)
end
end
if sequence
sql = "SELECT #{literal(sequence)}.currval FROM dual"
statement(conn) do |stmt|
begin
rs = log_connection_yield(sql, conn){stmt.executeQuery(sql)}
rs.next
rs.getLong(1)
rescue java.sql.SQLException
nil
end
end
end
end
# Primary key indexes appear to start with sys_ on Oracle
def primary_key_index_re
/\Asys_/i
end
def schema_parse_table(*)
sch = super
sch.each do |c, s|
if s[:type] == :decimal && s[:scale] == -127
s[:type] = :integer
elsif s[:db_type] == 'DATE'
s[:type] = :datetime
end
end
sch
end
def schema_parse_table_skip?(h, schema)
super || (h[:table_schem] != current_user unless schema)
end
# As of Oracle 9.2, releasing savepoints is no longer supported.
def supports_releasing_savepoints?
false
end
def setup_type_convertor_map
super
@type_convertor_map[:OracleDecimal] = ORACLE_DECIMAL
@type_convertor_map[:OracleClob] = ORACLE_CLOB
end
end
class Dataset < JDBC::Dataset
include Sequel::Oracle::DatasetMethods
NUMERIC_TYPE = Java::JavaSQL::Types::NUMERIC
TIMESTAMP_TYPE = Java::JavaSQL::Types::TIMESTAMP
CLOB_TYPE = Java::JavaSQL::Types::CLOB
TIMESTAMPTZ_TYPES = [Java::oracle.jdbc.OracleTypes::TIMESTAMPTZ, Java::oracle.jdbc.OracleTypes::TIMESTAMPLTZ].freeze
def type_convertor(map, meta, type, i)
case type
when NUMERIC_TYPE
if meta.getScale(i) == 0
map[:OracleDecimal]
else
super
end
when *TIMESTAMPTZ_TYPES
map[TIMESTAMP_TYPE]
when CLOB_TYPE
map[:OracleClob]
else
super
end
end
end
end
end
end
|