Class: PLSQL::JDBCConnection

Inherits:
Connection show all
Defined in:
lib/plsql/jdbc_connection.rb

Overview

:nodoc:

Defined Under Namespace

Classes: CallableStatement, Cursor

Constant Summary collapse

RUBY_CLASS_TO_SQL_TYPE =
{
  Fixnum => java.sql.Types::INTEGER,
  Bignum => java.sql.Types::INTEGER,
  Integer => java.sql.Types::INTEGER,
  Float => java.sql.Types::FLOAT,
  BigDecimal => java.sql.Types::NUMERIC,
  String => java.sql.Types::VARCHAR,
  Java::OracleSql::CLOB => Java::oracle.jdbc.OracleTypes::CLOB,
  Java::OracleSql::BLOB => Java::oracle.jdbc.OracleTypes::BLOB,
  Date => java.sql.Types::DATE,
  Time => java.sql.Types::TIMESTAMP,
  DateTime => java.sql.Types::DATE,
  Java::OracleSql::ARRAY => Java::oracle.jdbc.OracleTypes::ARRAY,
  Array => Java::oracle.jdbc.OracleTypes::ARRAY,
  Java::OracleSql::STRUCT => Java::oracle.jdbc.OracleTypes::STRUCT,
  Hash => Java::oracle.jdbc.OracleTypes::STRUCT,
  java.sql.ResultSet => Java::oracle.jdbc.OracleTypes::CURSOR,
}
SQL_TYPE_TO_RUBY_CLASS =
{
  java.sql.Types::CHAR => String,
  java.sql.Types::NCHAR => String,
  java.sql.Types::VARCHAR => String,
  java.sql.Types::NVARCHAR => String,
  java.sql.Types::LONGVARCHAR => String,
  java.sql.Types::NUMERIC => BigDecimal,
  java.sql.Types::INTEGER => Fixnum,
  java.sql.Types::DATE => Time,
  java.sql.Types::TIMESTAMP => Time,
  Java::oracle.jdbc.OracleTypes::TIMESTAMPTZ => Time,
  Java::oracle.jdbc.OracleTypes::TIMESTAMPLTZ => Time,
  java.sql.Types::BLOB => String,
  java.sql.Types::CLOB => String,
  java.sql.Types::ARRAY => Java::OracleSql::ARRAY,
  java.sql.Types::STRUCT => Java::OracleSql::STRUCT,
  Java::oracle.jdbc.OracleTypes::CURSOR => java.sql.ResultSet
}

Constants inherited from Connection

Connection::RUBY_TEMP_TABLE_PREFIX

Instance Attribute Summary

Attributes inherited from Connection

#activerecord_class, #raw_driver

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Connection

create, create_new, #describe_synonym, driver_type, #drop_all_ruby_temporary_tables, #drop_session_ruby_temporary_tables, #initialize, #jdbc?, #oci?, #raw_connection, #select_all, #select_first, #select_hash_all, #select_hash_first, #session_id, #time_zone

Constructor Details

This class inherits a constructor from PLSQL::Connection

Class Method Details

.create_raw(params) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/plsql/jdbc_connection.rb', line 41

def self.create_raw(params)
  database = params[:database]
  url = if ENV['TNS_ADMIN'] && database && !params[:host] && !params[:url]
    "jdbc:oracle:thin:@#{database}"
  else
    database = ":#{database}" unless database.match(/^(\:|\/)/)
    params[:url] || "jdbc:oracle:thin:@#{params[:host] || 'localhost'}:#{params[:port] || 1521}#{database}"
  end
  new(java.sql.DriverManager.getConnection(url, params[:username], params[:password]))
end

Instance Method Details

#autocommit=(value) ⇒ Object



77
78
79
# File 'lib/plsql/jdbc_connection.rb', line 77

def autocommit=(value)
  raw_connection.setAutoCommit(value)
end

#autocommit?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/plsql/jdbc_connection.rb', line 73

def autocommit?
  raw_connection.getAutoCommit
end

#commitObject



65
66
67
# File 'lib/plsql/jdbc_connection.rb', line 65

def commit
  raw_connection.commit
end

#cursor_from_query(sql, bindvars = [], options = {}) ⇒ Object



198
199
200
# File 'lib/plsql/jdbc_connection.rb', line 198

def cursor_from_query(sql, bindvars=[], options={})
  Cursor.new_from_query(self, sql, bindvars, options)
end

#database_versionObject



511
512
513
514
515
516
517
518
519
520
521
522
523
# File 'lib/plsql/jdbc_connection.rb', line 511

def database_version
  @database_version ||= if md = raw_connection.
    major = md.getDatabaseMajorVersion
    minor = md.getDatabaseMinorVersion
    if md.getDatabaseProductVersion =~ /#{major}\.#{minor}\.(\d+)\.(\d+)/
      update = $1.to_i
      patch = $2.to_i
    else
      update = patch = 0
    end
    [major, minor, update, patch]
  end
end

#exec(sql, *bindvars) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/plsql/jdbc_connection.rb', line 85

def exec(sql, *bindvars)
  cs = prepare_call(sql, *bindvars)
  cs.execute
  true
ensure
  cs.close rescue nil
end

#get_bind_variable(stmt, i, type) ⇒ Object



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/plsql/jdbc_connection.rb', line 305

def get_bind_variable(stmt, i, type)
  case type.to_s.to_sym
  when :Fixnum, :Bignum, :Integer
    stmt.getInt(i)
  when :Float
    stmt.getFloat(i)
  when :BigDecimal
    bd = stmt.getBigDecimal(i)
    bd && BigDecimal.new(bd.to_s)
  when :String
    stmt.getString(i)
  when :'Java::OracleSql::CLOB'
    stmt.getClob(i)
  when :'Java::OracleSql::BLOB'
    stmt.getBlob(i)
  when :Date, :DateTime
    stmt.getDATE(i)
  when :Time
    stmt.getTimestamp(i)
  when :'Java::OracleSql::ARRAY'
    stmt.getArray(i)
  when :'Java::OracleSql::STRUCT'
    stmt.getSTRUCT(i)
  when :'Java::JavaSql::ResultSet'
    stmt.getCursor(i)
  end
end

#get_java_sql_type(value, type) ⇒ Object



256
257
258
# File 'lib/plsql/jdbc_connection.rb', line 256

def get_java_sql_type(value, type)
  RUBY_CLASS_TO_SQL_TYPE[type || value.class] || java.sql.Types::VARCHAR
end

#get_ruby_value_from_result_set(rset, i, metadata) ⇒ Object



333
334
335
336
337
# File 'lib/plsql/jdbc_connection.rb', line 333

def get_ruby_value_from_result_set(rset, i, )
  ruby_type = SQL_TYPE_TO_RUBY_CLASS[[:sql_type]]
  ora_value = get_bind_variable(rset, i, ruby_type)
  result_new = ora_value_to_ruby_value(ora_value)
end

#logoffObject



57
58
59
60
61
62
63
# File 'lib/plsql/jdbc_connection.rb', line 57

def logoff
  super
  raw_connection.close
  true
rescue
  false
end

#ora_value_to_ruby_value(value) ⇒ Object



467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
# File 'lib/plsql/jdbc_connection.rb', line 467

def ora_value_to_ruby_value(value)
  case value
  when Float, BigDecimal
    ora_number_to_ruby_number(value)
  when Java::JavaMath::BigDecimal
    value && ora_number_to_ruby_number(BigDecimal.new(value.to_s))
  when Java::OracleSql::DATE
    if value
      d = value.dateValue
      t = value.timeValue
      Time.send(plsql.default_timezone, d.year + 1900, d.month + 1, d.date, t.hours, t.minutes, t.seconds)
    end
  when Java::JavaSql::Timestamp
    if value
      Time.send(plsql.default_timezone, value.year + 1900, value.month + 1, value.date, value.hours, value.minutes, value.seconds,
        value.nanos / 1000)
    end
  when Java::OracleSql::CLOB
    if value.isEmptyLob
      nil
    else
      value.getSubString(1, value.length)
    end
  when Java::OracleSql::BLOB
    if value.isEmptyLob
      nil
    else
      String.from_java_bytes(value.getBytes(1, value.length))
    end
  when Java::OracleSql::ARRAY
    value.getArray.map{|e| ora_value_to_ruby_value(e)}
  when Java::OracleSql::STRUCT
    descriptor = value.getDescriptor
     = descriptor.
    field_names = (1..descriptor.getLength).map {|i| .getColumnName(i).downcase.to_sym}
    field_values = value.getAttributes.map{|e| ora_value_to_ruby_value(e)}
    ArrayHelpers::to_hash(field_names, field_values)
  when Java::java.sql.ResultSet
    Cursor.new(self, value)
  else
    value
  end
end

#parse(sql) ⇒ Object



194
195
196
# File 'lib/plsql/jdbc_connection.rb', line 194

def parse(sql)
  CallableStatement.new(self, sql)
end

#plsql_to_ruby_data_type(metadata) ⇒ Object



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
# File 'lib/plsql/jdbc_connection.rb', line 343

def plsql_to_ruby_data_type()
  data_type, data_length = [:data_type], [:data_length]
  case data_type
  when "VARCHAR2", "CHAR", "NVARCHAR2", "NCHAR"
    [String, data_length || 32767]
  when "CLOB", "NCLOB"
    [Java::OracleSql::CLOB, nil]
  when "BLOB"
    [Java::OracleSql::BLOB, nil]
  when "NUMBER"
    [BigDecimal, nil]
  when "PLS_INTEGER", "BINARY_INTEGER"
    [Fixnum, nil]
  when "DATE"
    [DateTime, nil]
  when "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "TIMESTAMP WITH LOCAL TIME ZONE"
    [Time, nil]
  when "TABLE", "VARRAY"
    [Java::OracleSql::ARRAY, nil]
  when "OBJECT"
    [Java::OracleSql::STRUCT, nil]
  when "REF CURSOR"
    [java.sql.ResultSet, nil]
  else
    [String, 32767]
  end
end

#prefetch_rows=(value) ⇒ Object



81
82
83
# File 'lib/plsql/jdbc_connection.rb', line 81

def prefetch_rows=(value)
  raw_connection.setDefaultRowPrefetch(value)
end

#prepare_call(sql, *bindvars) ⇒ Object



210
211
212
213
214
215
216
# File 'lib/plsql/jdbc_connection.rb', line 210

def prepare_call(sql, *bindvars)
  stmt = raw_connection.prepareCall(sql)
  bindvars.each_with_index do |bv, i|
    set_bind_variable(stmt, i+1, bv)
  end
  stmt
end

#prepare_statement(sql, *bindvars) ⇒ Object



202
203
204
205
206
207
208
# File 'lib/plsql/jdbc_connection.rb', line 202

def prepare_statement(sql, *bindvars)
  stmt = raw_connection.prepareStatement(sql)
  bindvars.each_with_index do |bv, i|
    set_bind_variable(stmt, i+1, ruby_value_to_ora_value(bv))
  end
  stmt
end

#result_set_to_ruby_data_type(column_type, column_type_name) ⇒ Object



339
340
341
# File 'lib/plsql/jdbc_connection.rb', line 339

def result_set_to_ruby_data_type(column_type, column_type_name)

end

#rollbackObject



69
70
71
# File 'lib/plsql/jdbc_connection.rb', line 69

def rollback
  raw_connection.rollback
end

#ruby_value_to_ora_value(value, type = nil, metadata = {}) ⇒ Object



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/plsql/jdbc_connection.rb', line 371

def ruby_value_to_ora_value(value, type=nil, ={})
  type ||= value.class
  case type.to_s.to_sym
  when :Fixnum
    value
  when :String
    value.to_s
  when :BigDecimal
    case value
    when TrueClass
      java_bigdecimal(1)
    when FalseClass
      java_bigdecimal(0)
    else
      java_bigdecimal(value)
    end
  when :Date, :DateTime
    case value
    when DateTime
      java_date(Time.send(plsql.default_timezone, value.year, value.month, value.day, value.hour, value.min, value.sec))
    when Date
      java_date(Time.send(plsql.default_timezone, value.year, value.month, value.day, 0, 0, 0))
    else
      java_date(value)
    end
  when :Time
    java_timestamp(value)
  when :'Java::OracleSql::CLOB'
    if value
      clob = Java::OracleSql::CLOB.createTemporary(raw_connection, false, Java::OracleSql::CLOB::DURATION_SESSION)
      clob.setString(1, value)
      clob
    else
      nil
    end
  when :'Java::OracleSql::BLOB'
    if value
      blob = Java::OracleSql::BLOB.createTemporary(raw_connection, false, Java::OracleSql::BLOB::DURATION_SESSION)
      blob.setBytes(1, value.to_java_bytes)
      blob
    else
      nil
    end
  when :'Java::OracleSql::ARRAY'
    if value
      raise ArgumentError, "You should pass Array value for collection type parameter" unless value.is_a?(Array)
      descriptor = Java::OracleSql::ArrayDescriptor.createDescriptor([:sql_type_name], raw_connection)
      elem_type = descriptor.getBaseType
      elem_type_name = descriptor.getBaseName
      elem_list = value.map do |elem|
        case elem_type
        when Java::oracle.jdbc.OracleTypes::ARRAY
          ruby_value_to_ora_value(elem, Java::OracleSql::ARRAY, :sql_type_name => elem_type_name)
        when Java::oracle.jdbc.OracleTypes::STRUCT
          ruby_value_to_ora_value(elem, Java::OracleSql::STRUCT, :sql_type_name => elem_type_name)
        else
          ruby_value_to_ora_value(elem)
        end
      end
      Java::OracleSql::ARRAY.new(descriptor, raw_connection, elem_list.to_java)
    end
  when :'Java::OracleSql::STRUCT'
    if value
      raise ArgumentError, "You should pass Hash value for object type parameter" unless value.is_a?(Hash)
      descriptor = Java::OracleSql::StructDescriptor.createDescriptor([:sql_type_name], raw_connection)
       = descriptor.
      struct_fields = (1..descriptor.getLength).inject({}) do |hash, i|
        hash[.getColumnName(i).downcase.to_sym] =
          {:type => .getColumnType(i), :type_name => .getColumnTypeName(i)}
        hash
      end
      object_attrs = java.util.HashMap.new
      value.each do |key, attr_value|
        raise ArgumentError, "Wrong object type field passed to PL/SQL procedure" unless (field = struct_fields[key])
        case field[:type]
        when Java::oracle.jdbc.OracleTypes::ARRAY
          # nested collection
          object_attrs.put(key.to_s.upcase, ruby_value_to_ora_value(attr_value, Java::OracleSql::ARRAY, :sql_type_name => field[:type_name]))
        when Java::oracle.jdbc.OracleTypes::STRUCT
          # nested object type
          object_attrs.put(key.to_s.upcase, ruby_value_to_ora_value(attr_value, Java::OracleSql::STRUCT, :sql_type_name => field[:type_name]))
        else
          object_attrs.put(key.to_s.upcase, ruby_value_to_ora_value(attr_value))
        end
      end
      Java::OracleSql::STRUCT.new(descriptor, raw_connection, object_attrs)
    end
  when :'Java::JavaSql::ResultSet'
    if value
      value.result_set
    end
  else
    value
  end
end

#set_bind_variable(stmt, i, value, type = nil, length = nil, metadata = {}) ⇒ Object



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/plsql/jdbc_connection.rb', line 260

def set_bind_variable(stmt, i, value, type=nil, length=nil, ={})
  key = i.kind_of?(Integer) ? nil : i.to_s.gsub(':','')
  type_symbol = (!value.nil? && type ? type : value.class).to_s.to_sym
  case type_symbol
  when :Fixnum, :Bignum, :Integer
    stmt.send("setInt#{key && "AtName"}", key || i, value)
  when :Float
    stmt.send("setFloat#{key && "AtName"}", key || i, value)
  when :BigDecimal, :'Java::JavaMath::BigDecimal'
    stmt.send("setBigDecimal#{key && "AtName"}", key || i, value)
  when :String
    stmt.send("setString#{key && "AtName"}", key || i, value)
  when :'Java::OracleSql::CLOB'
    stmt.send("setClob#{key && "AtName"}", key || i, value)
  when :'Java::OracleSql::BLOB'
    stmt.send("setBlob#{key && "AtName"}", key || i, value)
  when :Date, :DateTime, :'Java::OracleSql::DATE'
    stmt.send("setDATE#{key && "AtName"}", key || i, value)
  when :Time, :'Java::JavaSql::Timestamp'
    stmt.send("setTimestamp#{key && "AtName"}", key || i, value)
  when :NilClass
    if ['TABLE', 'VARRAY', 'OBJECT'].include?([:data_type])
      stmt.send("setNull#{key && "AtName"}", key || i, get_java_sql_type(value, type),
        [:sql_type_name])
    elsif [:data_type] == 'REF CURSOR'
      # TODO: cannot bind NULL value to cursor parameter, getting error
      # java.sql.SQLException: Unsupported feature: sqlType=-10
      # Currently do nothing and assume that NULL values will not be passed to IN parameters
      # If cursor is IN/OUT or OUT parameter then it should work
    else
      stmt.send("setNull#{key && "AtName"}", key || i, get_java_sql_type(value, type))
    end
  when :'Java::OracleSql::ARRAY'
    stmt.send("setARRAY#{key && "AtName"}", key || i, value)
  when :'Java::OracleSql::STRUCT'
    stmt.send("setSTRUCT#{key && "AtName"}", key || i, value)
  when :'Java::JavaSql::ResultSet'
    # TODO: cannot find how to pass cursor parameter from JDBC
    # setCursor is giving exception java.sql.SQLException: Unsupported feature
    stmt.send("setCursor#{key && "AtName"}", key || i, value)
  else
    raise ArgumentError, "Don't know how to bind variable with type #{type_symbol}"
  end
end

#set_time_zone(time_zone = nil) ⇒ Object



52
53
54
55
# File 'lib/plsql/jdbc_connection.rb', line 52

def set_time_zone(time_zone=nil)
  time_zone ||= ENV['TZ']
  raw_connection.setSessionTimeZone(time_zone)
end