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



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

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

#autocommit?Boolean

Returns:

  • (Boolean)


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

def autocommit?
  raw_connection.getAutoCommit
end

#commitObject



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

def commit
  raw_connection.commit
end

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



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

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

#database_versionObject



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

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



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

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



304
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
# File 'lib/plsql/jdbc_connection.rb', line 304

def get_bind_variable(stmt, i, type)
  case type.to_s.to_sym
  when :Fixnum, :Bignum, :Integer
    stmt.getObject(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



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

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



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

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



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

def logoff
  super
  raw_connection.close
  true
rescue
  false
end

#ora_value_to_ruby_value(value) ⇒ Object



466
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
# File 'lib/plsql/jdbc_connection.rb', line 466

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



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

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

#plsql_to_ruby_data_type(metadata) ⇒ Object



342
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
# File 'lib/plsql/jdbc_connection.rb', line 342

def plsql_to_ruby_data_type()
  data_type, data_length = [:data_type], [:data_length]
  case data_type
  when "VARCHAR", "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 "NATURAL", "NATURALN", "POSITIVE", "POSITIVEN", "SIGNTYPE", "SIMPLE_INTEGER", "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



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

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

#prepare_call(sql, *bindvars) ⇒ Object



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

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



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

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



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

def result_set_to_ruby_data_type(column_type, column_type_name)

end

#rollbackObject



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

def rollback
  raw_connection.rollback
end

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



370
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
# File 'lib/plsql/jdbc_connection.rb', line 370

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



259
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
# File 'lib/plsql/jdbc_connection.rb', line 259

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','XMLTYPE'].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
# File 'lib/plsql/jdbc_connection.rb', line 52

def set_time_zone(time_zone=nil)
  raw_connection.setSessionTimeZone(time_zone) if time_zone
end